目录
前言
一、什么是队列?
概念:队列是一种特殊的线性表,队列的插入和删除被限制在表的两端,即插入操作只能在表的一端进行,而删除操作只能在表的另一端进行,因此队列又称先进先出表。
理解:队列这个概念非常好理解,你可以把它想象成排队买票,先来的先买,后来的人只能站末尾,不允许插队,先进者先出,这就是典型的队列。
1、顺序队列
顺序队列是用数组实现的,首指针在出队的时候移动,尾指针在入队的时候移动,需要考虑队列为空和队列为满的两种情况 。
顺序队列主要在于两个指针:一个是队头指针front,它指向队头元素;另一个是队尾指针rear,它指向下一个入队的元素存储位置。
(1)当一个队列插入一个元素,这时候队尾指针rear要加1,因为元素多了一个;
(2)当一个队列删除一个元素,这时候队头指针front也要增加1,因为队头从一开始的0位置变成了1位置,0位置的数据被删除了。
(3)当队头front与队尾rear相等的时候:front=rear,队列中没有任何元素,称为空队列。
顺序队列中的溢出现象:
(1) "下溢"现象:当队列为空时,做出队运算产生的溢出现象。“下溢”是正常现象,常用作程序控制转移的条件。
(2)"真上溢"现象:当队列满时,做进栈运算产生空间溢出的现象。“真上溢”是一种出错状态,应设法避免。
(3)"假上溢"现象:由于入队和出队操作中,头尾指针只增加不减小,致使被删元素的空间永远无法重新利用。当队列中实际的元素个数远远小于向量空间的规模时,也可能由于尾指针已超越向量空间的上界而不能做入队操作。该现象称为"假上溢"现象。
2、循环队列
很好理解,如果删除队列的元素,队头指针从0开始变大,那么0123这些删除的位置不就空了,怎么办呢,这时候把首位接在一起,让队尾可以循环使用空的存储位置,是的空间可以重复使用。
在循环队列中,当队列为空时,有front=rear;
而当所有队列空间全占满时,也有front=rear。
为了区别这两种情况,规定循环队列最多只能有最大长度(MaxSize-1)个队列元素,当循环队列中只剩下一个空存储单元时,队列就已经满了。
因此,队列判空的条件时front=rear;
而队列判满的条件时front=(rear+1)%MaxSize。
队空和队满的情况如图:
循环队列还可以有效的解决顺序队列假溢出的缺点。
二、队列简单案例
创建一个对象,定义一个数组,写入队、出队、判断是否为空的方法
package demo2;
public class MyQueue{
int[] elements;
public MyQueue(){
elements=new int[0];
}
//入队
public void add(int element){
//创建一个新的数组
int[] newArr = new int[elements.length+1];
//把原数组中的元素复制到新数组中
for (int i=0;i<elements.length;i++){
newArr[i] = elements[i];
}
//把添加的元素放入新数组中
newArr[elements.length] = elements;
//使用新数组替换旧数组
elements = newArr;
}
//出队
public int poll(){
//把数组中的0个元素取出来
int elements = elements[0];
//创建一个新的数组
int[] newArr = new int[elements.length-1];
//复制原数组中的元素到新数组中
for(int i=0;i<newArr.length;i++){
newArr[i]=elements[i+1];
}
//替换数组
elements=newArr;
return element;
}
//判断队列是否为空
public boolean isEmpty(){
return elements.length==0;
}
}
创建测试类,测试队列方法。
package demo2.test;
import demo2.MyQueue;
public class TestMyQueue{
public static void main(String[] args){
//创建一个队列
MyQueue mq = new MyQueue();
//入队
mq.add(9);
mq.add(8);
mq.add(7);
//出队
System.out.println(mq.poll());
mq.add(6)
mq.add(5)
System.out.println(mq.poll());
//判断队列是否为空
System.out.println(mq.isEmpty());
}
}