队列,一种限定性的线性表。它只允许在表一端进行插入,而在表的另一端进行删除操作。
普通队列
基于此,我们定义了一个数据结构,包含首尾指针
class Queue{
Object[] data;
int front;
int rear;
}
置空队列时 ,将rear=front=-1;
public static Queue initEmptyQueue(){
Queue queue=new Queue();
queue.data=new Object[MAX_SIZE];
queue.front=-1;
queue.rear=-1;
return queue;
}
在不考虑队列为空的情况下,出队列头指针front++,在不考虑溢出的情况下,进队列尾指针rear++
public static boolean inQueue(Queue queue,Object value){
queue.data[++queue.rear]=value;
return true;
}
public static Object outQueue(Queue queue){
return queue.data[++queue.front];
}
但是这样会遇到问题,如下图
当队尾指针指向了数组的最后一个位置,而队头指针不在0号位置时,他会出现假溢出的现象,即数组中有空位置,但是默认已经满了。为了解决这一问题,我们引入了循环队列,即将队尾和对头连接起来
循环队列
循环队列的数据结构还是和普通队列一样,只不过在设置空队列时将,rear和front设为了MAX_SIZE-1
class CycleQueue {
Object[] data;
int front;
int rear;
}
public static CycleQueue initEmptyQueue(){
CycleQueue cycleQueue=new CycleQueue();
cycleQueue.data=new Object[MAX_SIZE];
cycleQueue.front=MAX_SIZE-1;
cycleQueue.rear=MAX_SIZE-1;
return cycleQueue;
}
在进行判空的时候,只需要判断front和rear是否相等
public static boolean isEmpty(CycleQueue cycleQueue){
if(cycleQueue.front==cycleQueue.rear)
return true;
return false;
}
接下来就是队列中最重要的两个函数,出队列和入队列。出队列的思想:当队列不为空的时候,将队列的第一个元素出出队列,用数学公式表达就是front=(front+1)%MAX_SIZE,然后返回该位置;进队列的思想是,先判断front指针和rear指针是否直接相邻,若是直接相邻,则表示队列已满,无法插入,若不相邻,则直接插入,插入的位置为:rear=(rear+1)%MAX_SIZE.
public static boolean inQueue(CycleQueue cycleQueue,Object value){
if((cycleQueue.rear+1)%MAX_SIZE==cycleQueue.front)
return false;
cycleQueue.rear=(cycleQueue.rear+1)%MAX_SIZE;
cycleQueue.data[cycleQueue.rear]=value;
return true;
}
public static Object outQueue(CycleQueue cycleQueue){
if(isEmpty(cycleQueue)){
return null;
}
cycleQueue.front=(cycleQueue.front+1)%MAX_SIZE;
return cycleQueue.data[cycleQueue.front];
}
链队列
为甚么要使用练队列呢?其实和链栈的思想是一致的,因为顺序队列总是需要分配固定的内存空间,若分配过大,容易造成空间浪费,若是分配过小,容易造成溢出,所以我们才使用了链队列,在使用的过程中动态的分配空间。首先先看一下链队列的数据结构
//将头尾指针封装在一起
class LinkQueue{
Node rear;
Node front;
}
//链队列节点的类型
class Node{
Node next;
Object value;
}
首先创建一个带头结点的空队列
public static LinkQueue initEmptyLinkQueue(){
LinkQueue linkQueue=new LinkQueue();
Node head=new Node();
head.next=null;
linkQueue.rear=linkQueue.front=head;
return linkQueue;
}
判断队列是否为空的思想和循环队列相同,即判断头尾指针是否相等
public static boolean isEmpty(LinkQueue linkQueue){
if(linkQueue.rear==linkQueue.front)
return true;
return false;
}
最后看进队列和出队列两个函数。进队列的思想是:利用单链表尾插法的思想插入到链表的尾部,具体可参考单链表的创建;出队列的思想是:如果队列不为空,则将对列的头指针指向第一个节点的下一个节点,然后返回第一个节点的值。
public static boolean inQueue(LinkQueue linkQueue,Object value){
Node node=new Node();
node.value=value;
node.next=linkQueue.rear.next;
linkQueue.rear.next=node;
linkQueue.rear=node;
return true;
}
public static Object outQueue(LinkQueue linkQueue){
if(isEmpty(linkQueue)){
return null;
}
Node node=linkQueue.front.next;
linkQueue.front.next=node.next;
if(linkQueue.front.next==null)
linkQueue.rear=linkQueue.front;
return node.value;
}
至此。队列的基本操作就完成了。