【栈和队列】5、队列概述与数组队列的基本实现 - Java
3-5 数组队列
简单记录 - bobo老师的玩转算法系列–玩转数据结构 - 栈和队列
队列Queue
- 队列也是一种线性结构
- 相比数组,队列对应的操作是数组的子集
- 只能从一端(队尾)添加元素,只能从另一端(队首)取出元素 先进先出
队尾 队首
队列是一种先进先出的数据结构(先到先得)
First In First Out(FIFO)
队列
Queue<E>
- void enqueue(E)
- E dequeue()
- E getFront()
- int getSize()
- boolean isEmpty()
enqueue(E)入队 dequeue()出队
getFront()得到队首元素 getSize()得到总共元素的个数
isEmpty()队列是否为空
从用户的角度看,支持这些操作就好
具体底层实现,用户不关心
实际底层有多种实现方式
我们开发者要深入理解、实现
那就去实现队列吧
ArrayQueue<E> implement Interface Queue<E>
- void enqueue(E)
- E dequeue()
- E getFront()
- int getSize()
- boolean isEmpty()
ArrayQueue实现了Queue接口
实践 : 数组队列的实现
动态数组 Array
public class Array<E> {
private E[] data;
private int size;
// 构造函数,传入数组的容量capacity构造Array
public Array(int capacity){
data = (E[])new Object[capacity];
size = 0;
}
// 无参数的构造函数,默认数组的容量capacity=10
public Array(){
this(10);
}
// 获取数组的容量
public int getCapacity(){
return data.length;
}
// 获取数组中的元素个数
public int getSize(){
return size;
}
// 返回数组是否为空
public boolean isEmpty(){
return size == 0;
}
// 在index索引的位置插入一个新元素e
public void add(int index, E e){
if(index < 0 || index > size)
throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");
if(size == data.length)
resize(2 * data.length);
for(int i = size - 1; i >= index ; i --)
data[i + 1] = data[i];
data[index] = e;
size ++;
}
// 向所有元素后添加一个新元素
public void addLast(E e){
add(size, e);
}
// 在所有元素前添加一个新元素
public void addFirst(E e){
add(0, e);
}
// 获取index索引位置的元素
public E get(int index){
if(index < 0 || index >= size)
throw new IllegalArgumentException("Get failed. Index is illegal.");
return data[index];
}
public E getLast(){
return get(size - 1);
}
public E getFirst(){
return get(0);
}
// 修改index索引位置的元素为e
public void set(int index, E e){
if(index < 0 || index >= size)
throw new IllegalArgumentException("Set failed. Index is illegal.");
data[index] = e;
}
// 查找数组中是否有元素e
public boolean contains(E e){
for(int i = 0 ; i < size ; i ++){
if(data[i].equals(e))
return true;
}
return false;
}
// 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
public int find(E e){
for(int i = 0 ; i < size ; i ++){
if(data[i].equals(e))
return i;
}
return -1;
}
// 从数组中删除index位置的元素, 返回删除的元素
public E remove(int index){
if(index < 0 || index >= size)
throw new IllegalArgumentException("Remove failed. Index is illegal.");
E ret = data[index];
for(int i = index + 1 ; i < size ; i ++)
data[i - 1] = data[i];
size --;
data[size] = null; // loitering objects != memory leak
if(size == data.length / 4 && data.length / 2 != 0)
resize(data.length / 2);
return ret;
}
// 从数组中删除第一个元素, 返回删除的元素
public E removeFirst(){
return remove(0);
}
// 从数组中删除最后一个元素, 返回删除的元素
public E removeLast(){
return remove(size - 1);
}
// 从数组中删除元素e
public void removeElement(E e){
int index = find(e);
if(index != -1)
remove(index);
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));
res.append('[');
for(int i = 0 ; i < size ; i ++){
res.append(data[i]);
if(i != size - 1)
res.append(", ");
}
res.append(']');
return res.toString();
}
// 将数组空间的容量变成newCapacity大小
private void resize(int newCapacity){
E[] newData = (E[])new Object[newCapacity];
for(int i = 0 ; i < size ; i ++)
newData[i] = data[i];
data = newData;
}
}
队列接口 Queue interface
public interface Queue<E> {
int getSize();
boolean isEmpty();
void enqueue(E e);
E dequeue();
E getFront();
}
数组队列的实现 ArrayQueue
public class ArrayQueue<E> implements Queue<E> {
private Array<E> array;
public ArrayQueue(int capacity){
array = new Array<>(capacity);
}
public ArrayQueue(){
array = new Array<>();
}
@Override
public int getSize(){
return array.getSize();
}
@Override
public boolean isEmpty(){
return array.isEmpty();
}
public int getCapacity(){
return array.getCapacity();
}
@Override
public void enqueue(E e){
array.addLast(e);
}
@Override
public E dequeue(){
return array.removeFirst();
}
@Override
public E getFront(){
return array.getFirst();
}
@Override
public String toString(){
StringBuilder res = new StringBuilder();
res.append("Queue: ");
res.append("front [");
for(int i = 0 ; i < array.getSize() ; i ++){
res.append(array.get(i));
if(i != array.getSize() - 1)
res.append(", ");
}
res.append("] tail");
return res.toString();
}
}
测试
Main
/**
* @author Liu Awen Email:willowawen@gmail.com
* @create 2020-02-16 0:02
*/
public class Main {
public static void main(String[] args) {
ArrayQueue<Integer> queue = new ArrayQueue<>();
for(int i = 0 ; i < 5 ; i ++){
queue.enqueue(i);
System.out.println(queue);
}
System.out.println("-----------");
System.out.println("isEmpty:" + queue.isEmpty());
System.out.println("Size:" + queue.getSize());
System.out.println(queue);
System.out.println("队首元素:" + queue.getFront());
System.out.println(queue);
System.out.println("----------");
for(int i = 0 ; i < 5 ; i ++){
System.out.println(queue);
queue.dequeue();
}
System.out.println(queue);
}
}
Result
D:\Environments\jdk-11.0.2\bin\java.exe -javaagent:D:\Java\ideaIU-2019.2.win\lib\idea_rt.jar=1352:D:\Java\ideaIU-2019.2.win\bin -Dfile.encoding=UTF-8 -classpath D:\IdeaProjects\imooc\Play-with-Data-Structures\03-Stacks-and-Queues\05-Array-Queue\target\classes Main
Queue: front [0] tail
Queue: front [0, 1] tail
Queue: front [0, 1, 2] tail
Queue: front [0, 1, 2, 3] tail
Queue: front [0, 1, 2, 3, 4] tail
-----------
isEmpty:false
Size:5
Queue: front [0, 1, 2, 3, 4] tail
队首元素:0
Queue: front [0, 1, 2, 3, 4] tail
----------
Queue: front [0, 1, 2, 3, 4] tail
Queue: front [1, 2, 3, 4] tail
Queue: front [2, 3, 4] tail
Queue: front [3, 4] tail
Queue: front [4] tail
Queue: front [] tail
Process finished with exit code 0
队列先进先出
数组队列的复杂度分析
ArrayQueue<E>
- void enqueue(E) O(1) 均摊
- E dequeue() O(n)
- E getFront() O(1)
- int getSize() O(1)
- boolean isEmpty() O(1)
【栈和队列】5、队列概述与数组队列的基本实现 - Java的更多相关文章
- C语言 简单的队列(数组队列)
//简单的队列 #include<stdio.h> #include<stdlib.h> #define datatype int #define N 10 //定义队列结构体 ...
- 算法进阶面试题02——BFPRT算法、找出最大/小的K个数、双向队列、生成窗口最大值数组、最大值减最小值小于或等于num的子数组数量、介绍单调栈结构(找出临近的最大数)
第二课主要介绍第一课余下的BFPRT算法和第二课部分内容 1.BFPRT算法详解与应用 找到第K小或者第K大的数. 普通做法:先通过堆排序然后取,是n*logn的代价. // O(N*logK) pu ...
- 队列的C++实现(数组)——创建-进队-出队-返回队首元素-清空队列栈-处理队列
队列的数组实现,从队尾进入,对头删除. 队列长度用标志变量size,它是独立于front和rear的一个变量.size == 0,队列为空.size == capacity,满队列. 一.结点声明 s ...
- Java数据类型Stack栈、Queue队列、数组队列和循环队列的比较
判断括号是否匹配:调用java本身 import java.util.Stack; public class Solution { public boolean isValid(String s){ ...
- Python与数据结构[2] -> 队列/Queue[0] -> 数组队列的 Python 实现
队列 / Queue 数组队列 数组队列是队列基于数组的一种实现,其实现类似于数组栈,是一种FIFO的线性数据结构. Queue: <--| 1 | 2 | 3 | 4 | 5 |<-- ...
- (四)循环队列 VS 数组队列 (效率对比)
目录 背景 测试代码 结果 链表 随机访问 背景 各自完成插入 10万.20万 条随机数,然后再将这些随机数出队列 : 测试代码 /** * 测试速度 */ public String testSpe ...
- 数组队列如何手撕?解密ArrayBlockingQueue的实现内幕!
队列 聊起队列,你一定会联想到一个与队列相似的数据结构:栈. 为了更好的理解什么是队列,我们将它和栈来比较一下: 队列的特点是:先进先出,如下图,1先进,1就先出. 图1:队列的图解 栈的特点是:先进 ...
- Java中的自定义数组队列
在Java中,作为所有数据结构中存储和获取速度最快的一种,数组凭借其这种简单易用的优势在各个方面都能大显神威.但是数组也有自身的局限性.数组的长度必须是固定的一旦定义之后就无法动态的更改,这就会造成这 ...
- C# 高性能的数组 高性能数组队列实战 HslCommunication的SharpList类详解
本文将使用一个gitHub开源的组件技术来实现这个功能 github地址:https://github.com/dathlin/HslCommunication ...
随机推荐
- viewer使用
一款pc端,点击放大,缩放,翻转等功能的插件.
- MySQL5.7 主主复制配置
MySQL 5.7 主主复制配置 一.简介: MySQL主主复制其实就是两个MySQL主从复制组合到一起,接着我的上一篇博客<centos 7 配置 mysql 5.7 主从复制>配置即可 ...
- 前端使用canvas生成盲水印的加密解密
为了保障信息安全,防止重大信息泄露,并且能够锁定泄露用户,需要对页面展示的图片加入当前用户信息的盲水印,即最终图片外观看起来和原图一样,但是经过解码以后可以识别出水印信息,并且在截图后仍能进行较好的识 ...
- JavaSE06-面向对象
1. 类和对象 1.1 类和对象的理解 客观存在的事物皆为对象 ,所以我们也常常说万物皆对象. 类 类的理解 类是对现实生活中一类具有共同属性和行为的事物的抽象 类是对象的数据类型,类是具有相同属性和 ...
- 详解双向链表的基本操作(C语言)
@ 目录 1.双向链表的定义 2.双向链表的创建 3.双向链表的插入 4.双向链表的删除 5.双向链表更改节点数据 6.双向链表的查找 7.双向链表的打印 8.测试函数及结果 1.双向链表的定义 上一 ...
- 05-flask基础补充
flask数据获取 request.args - 请求参数 request.form - 请求参数 request.files - 请求文件 request.cookies - 请求cookies r ...
- IDEA的基本操作——导入导出jar包
在使用Jmeter工具测试时,有时也需要导出jar包,测试对应功能,或者自己二次开发Jmeter工具,也是需要导出jar包的.既然经常用,所以就总结了下导入导出jar包的方法. 导入jar包 先打开i ...
- SQL注入及如何解决
SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗 ...
- 用Python实现童年小游戏贪吃蛇
贪吃蛇作为一款经典小游戏,早在 1976 年就面世了,我最早接触它还是在家长的诺基亚手机中.
- linux不同环境变量文件的比较,如/etc/profile和/etc/environment
/etc/profile 为系统的每个用户设置环境信息和启动程序,当用户第一次登录时,该文件被执行,其配置对所有登录的用户都有效. 当被修改时,必须重启才会生效.英文描述:"System w ...