什么是队列?
队列是一种特殊的线性表(线性结构),特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。因为队列只允许在一端插入,在另一端删除,所以只有最早进入队列的元素才能最先从队列中删除,故队列又称为先进先出(FIFO—first in first out)线性表。-------------摘自百度百科
队列按照逻辑数据结构可以分为顺序队列和循环队列.
顺序队列存在假溢出的现象,如下图所示.
队列中的元素只能从尾部入队,从头部出队.如果这时 a1,a2 出队,front 后移动到 2,如图:
但是现在队列明明有三个空位,却只能向队列中存一个元素,这就是假溢出,针对这种情况,提出了循环队列的概念,就是后面满了,就再从头开始,也就是头尾相接的循环。
队列的实现方式
数组和链表
数组模拟队列的实现方式
(1) 我们用两个变量front和rear分别记录队列前后端的下标,front随着数据输出而改变,rear随着数据输入而改变,
front和rear的定义如下:
如下图所示:
(2) 数据入队(addQueue)
1) 将尾针往后移动: rear + 1 ,当front == rear 就说明这是个空队列了.
2) 若尾针 rear < maxSize -1 ,则新来的元素可以存入rear所在的位置处, rear = maxSize -1 说明队列满了.
3) front的初始索引为-1,指向队列的头部,是头部元素的前一个位置,rear的初始索引为-1,指向队列的尾部元素,
数组模拟循环队列的实现方式
这是对数组模拟队列的优化,我们在这里把数组看作是一个环形(通过front和rear取模来实现),我们需要注意以下几点:
1). front 变量的含义: front 就指向队列的第一个元素, 也就是说 arr[front] 就是队列的第一个元素 ,front 的初始值 = 0
2). rear 变量的含义:rear 指向队列的最后一个元素的后一个位置. 因为希望空出一个空间做为约定.rear 的初始值 = 0
3). 当队列满时,条件是 (rear + 1) % maxSize == front【满】
4). 对队列为空的条件, rear == front 空
5). 当我们这样分析, 队列中有效的数据的个数 (rear + maxSize - front) % maxSize //eg: rear = 1 front = 0 ,则只有一个元素在数组中.
6). 我们就可以在原来的队列上修改得到,一个环形队列
代码实现如下:
//数组实现循环队列,我们需要知道的常见方法定义(功能)有:判断队列是否为满,判断队列是否为空,添加数据到队列,出队,显示所有数据,显示队列有效数据个数,显示队列的头数据
/**
* @description:数组实现的循环队列
* @author: Tian
* @time: 2020/7/21 8:06
*/
class CircleArray {
private int maxSize;
private int[] arr; // 该数组存放数据,模拟队列
private int front; // 指向队列头部
private int rear; // 指向队列的尾部
public CircleArray(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
}
public boolean isFull() {
//尾索引的下一个为头索引时表示队列满,即将队列容量空出一个作为约定(!!!)
return (rear + 1) % maxSize == front;
}
public boolean isEmpty() {
return rear == front;
}
public void addQueue(int n) {
if (isFull()) {
System.out.println("队列满,无法加入..");
return;
}
arr[rear] = n;
rear = (rear + 1) % maxSize;
}
public int getQueue() {
if (isEmpty()) {
throw new RuntimeException("队列空~");
}
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
//当前队列的有效数据个数
public int size(){
return (rear+maxSize-front)%maxSize;
}
//遍历
public void showQueue(){
if (isEmpty()) {
System.out.println("队列为空,没有数据");
return;
}
int s =size();
for(int i = front ; i < front +s;i++){
System.out.println(arr[i%maxSize]);
}
}
}