一、介绍
队列是一种先进先出的有序数据结构,可以用数组或者链表来实现。
总的来说,数组模拟队列有两种情况
- 简单队列。当添加到最后一个位置的时候,队列就不能使用了
- 环形队列。当数组添加到最后一个位置的时候,如果前面因为取出元素有了空的位置,可以重复利用空出的位置。
我们可以通过很多方式来实现队列,比较常见的有数组和链表来实现
二、数组实现简单队列
(一)思路分析
使用数组来模拟队列也就是说把数据存放在数组中,实现思路如下:
- 定义的数据结构如下:
各个字段的含义如下:public class ArrayQueue { private int capacity; private Object[] data; private int putIndex; private int takeIndex;
capacity:可以存放的元素的个数,也就是数组的长度
data:用来存放元素的数组
putIndex:下一个可以放入元素的下标;
takeIndex:下一个能获取到元素的下标; - 初始的时候putIndex和takeIndex都为0,表示没有任何元素,结构如下:

- 加入元素之后,按照我们1里面putIndex的含义,下一个可以放入的元素下标应该+1,比如,当我们加入一个元素后,那么下一个可以放入的元素下标就是1了,当加入三个元素后,效果如下(红色背景表示已经存放了元素):

- 当取出元素的时候,会从头部取,这个时候,takeIndex下标后移,效果如下:

- 当putIndex到5的后面(就是最大容量capicity)的时候,表明已经满了,不能再添加元素
- 当takeIndex和putIndex相等的时候,表明队列已经空了,不能再取元素
(二)代码实现
package com.firewolf.javabase.s002_queue;
/**
* 不可复用的队列----使用数组实现。一旦添加满了,即便取走了前面的元素,也不能再添加元素
*/
public class ArrayQueue {
/**
* 默认容量为10
*/
private static final Integer DEFAULT_CAPICITY = 10;
/**
* 队列容量
*/
private int capacity;
/**
* 存放数据的容器
*/
private Object[] data;
/**
* index for next put
*/
private int putIndex;
/**
* index for next put
*/
private int takeIndex;
public ArrayQueue(int capacity) {
this.capacity = capacity;
data = new Object[this.capacity];
}
public ArrayQueue() {
this(DEFAULT_CAPICITY);
}
/**
* 添加元素到队列尾部
*
* @param el 要加入的元素
* @return 添加成功返回true, 否则返回false
*/
public boolean addElement(Object el) {
if (isFull()) {
System.out.println("队列已经满了");
return false;
}
data[putIndex++] = el;
return true;
}
/**
* 获取头部元素
*/
public Object getElement() {
if (isEmpty()) {
System.out.println("没有可以获取的元素了");
return null;
}
return data[takeIndex++];
}
/**
* 显示所有的队列元素
*/
public void showElements() {
for (int i = takeIndex; i < putIndex; i++) {
System.out.println(data[i]);
}
}
/**
* 获取元素个数
*/
public int size() {
return putIndex - takeIndex;
}
/**
* 是否满了
*/
public boolean isFull() {
return putIndex == capacity;
}
/**
* 是否为空
*/
public boolean isEmpty() {
return takeIndex == putIndex;
}
}
三、数组实现环形队列
环形队列要求能够对前面已经移除的元素位置进行复用,也就是说当出现如下情况的时候,并不能认为数组满了,从而能够继续添加元素。

如果是在简单队列里面,上面这种情况是队列已经满了,因为putIndex==capacity了,而实际上我们看的到0,1,2三个位置已经空出来了,我们可以循环利用,也就是说,下一个可以放元素的位置变成0就可以了,也就是说,应该形成如下结构:

(一)思路分析
- 构建如下数据结构
可以看到,相对于简单队列,多了一个count,各自含义如下:public class CyclicArrayQueue { private int capacity; private Object[] data; private int count; private int putIndex; private int takeIndex;
capacity:可以存放的元素的个数,也就是数组的长度
data:用来存放元素的数组
putIndex:下一个可以放入元素的下标;
takeIndex:下一个能获取到元素的下标;
count:队列中元素个数,方便能够判断队列空满情况,其实不要也是可以的,不过使用这个更加方便。 - 开始的时候,putIndex=takeIndex=0,count=0,此时没有任何元素,队列为空。
- 加入元素的时候,count加1,putIndex增加,如果putIndex==capacity了,证明到了数组的最后一个元素,那么下一个能存放数据的位置为0,总结为:putIndex = (putIndex+1)%capacity。
- 获取元素的时候,count减1,同时takeIndex增加,同样的,如果到了takeIndex==capacity,那么也要回到队列的头部。总结为:takeIndex = (takeIndex+1)%capacity。
- count==0的时候,表示队列为空,此时不能获取元素。
- count==capacity的时候,表示队列满了,不能加入元素。
(二)代码实现
package com.firewolf.javabase.s002_queue;
/**
* 可以循环复用的队列----数组实现
*/
public class CyclicArrayQueue {
/**
* 默认容量为10
*/
private static final Integer DEFAULT_CAPICITY = 10;
/**
* 队列容量
*/
private int capacity;
/**
* 存放数据的容器
*/
private Object[] data;
/**
* 已经存放的元素个数
*/
private int count;
/**
* index for next put
*/
private int putIndex;
/**
* index for next take
*/
private int takeIndex;
public CyclicArrayQueue(int capacity) {
this.capacity = capacity;
data = new Object[this.capacity];
}
public CyclicArrayQueue() {
this(DEFAULT_CAPICITY);
}
/**
* 添加元素到队列尾部
*
* @param el 要加入的元素
* @return 添加成功返回true, 否则返回false
*/
public boolean addElement(Object el) {
if (isFull()) {
System.out.println("队列已经满了");
return false;
}
count++; //元素数量+1
data[putIndex] = el; //放入元素
putIndex = (putIndex + 1) % capacity; //更新索引
return true;
}
/**
* 获取头部元素
*/
public Object getElement() {
if (isEmpty()) {
System.out.println("没有可以获取的元素了");
return null;
}
Object value = data[takeIndex]; //获取到元素
count--;//更新元素数量
takeIndex = (takeIndex + 1) % capacity;//更新索引
return value;
}
/**
* 显示所有的队列元素
*/
public void showElements() {
if (isEmpty()) {
System.out.println("没有元素");
return;
}
for (int i = takeIndex; i < takeIndex + count; i++) {
System.out.println(data[i % capacity]);
}
}
/**
* 获取元素个数
*/
public int size() {
return count;
}
/**
* 是否满了
*/
public boolean isFull() {
return count == capacity;
}
/**
* 是否为空
*/
public boolean isEmpty() {
return count == 0;
}
}
1850

被折叠的 条评论
为什么被折叠?



