队列
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
队列是一种先入先出的数据结构。结构示意图大概如下
队尾进入,队头出队,只能移除第一个元素。
代码的实现
下面展示 队列代码的实现
。
Class MyQueue{
//申请一个空间
privite List<Interger> data;
private int front;
//初始化
public MyQueue{
data=new ArrayList<Integer>();
front=0;
}
//判空
public boolean isEmpty(){
return front>=data.size;
}
//进队列
public boolean EnQueue(int value){
data.add(value);
return true;
}
//删除元素
public boolean DeQueue(){
if(isEmpty())
return false;
front++;
return true;
}
//获取第一个元素
public int Front(){
return data.get(front);
}
}
可以看出队列进队和出队的操作主要核心是对front这个指针的运用。front始终指向第一个元素,如果要删除则front向后面移动以为,但是也可以看出来这个队列的操作使用局限性的,当我们设定这个数组的最大长度为5的时候,我们只可以插入5个元素,如果还想要继续插入怎么办呢?
我们可以使用循环队列来解决这个问题。
循环队列
为充分利用向量空间,克服"假溢出"现象的方法是:将向量空间想象为一个首尾相接的圆环,并称这种向量为循环向量。存储在其中的队列称为循环队列(Circular Queue)。
循环队列结构大致如下图。
代码的实现
class MyCircularQueue {
//申明变量
private int[] data;
private int head;
private int tail;
private int size;
//初始化
public MyCircularQueue(int k) {
data = new int[k];
head = -1;
tail = -1;
size = k;
}
//进队列,进行判空和判满
public boolean enQueue(int value) {
if (isFull() == true) {
return false;
}
if (isEmpty() == true) {
head = 0;
}
tail = (tail + 1) % size;
data[tail] = value;
return true;
}
//从队列中移除
public boolean deQueue() {
if (isEmpty() == true) {
return false;
}
if (head == tail) {
head = -1;
tail = -1;
return true;
}
head = (head + 1) % size;
return true;
}
//获取队列头元素
public int Front() {
if (isEmpty() == true) {
return -1;
}
return data[head];
}
//获取队尾元素
public int Rear() {
if (isEmpty() == true) {
return -1;
}
return data[tail];
}
//判空的条件
public boolean isEmpty() {
return head == -1;
}
//判满的条件
public boolean isFull() {
return ((tail + 1) % size) == head;
}
}
可以从代码中看出来,循环队列比普通队列多了一个tail的指针,关于他的判空,在最开始设置head和tail都为-1,如果head=-1,则说明队列为空;关于判满,如果(tail+1)%size==head,也就是说tail的下一个元素为head则判断为满,这也是为什么在添加和删除的时候我们都是用先加一在除size,这样就保证的tail和head的值不会超过size,那么这是怎么进行入队的呢?
可以从代码中看出先判断空和满,然后将tail指向下一个元素的索引号,将data[tail]=value,
怎么进行删除的呢?同样的,先要对队列判断是否为空,是否head和tail相等,然后将head指向下一个索引号,可以看出,循环队列操作的核心就是对head和tail俩个指针的使用。