目录
队列是一种只允许在一端插入数据(队尾),在另一端删除数据(队头)的操作的特殊线性表。
队列的特点:先进先出
队列可以用数组实现,称为顺序队列,又叫循环队列。也可以用链表实现,称为链式队列。
链式队列:
入队头插:O(1), 出队队尾出:O(n)[出队不知道队尾的前驱]
入队尾插:O(n),出队队头出:O(1)
若想要入队和出队的时间复杂度都为O(1),则需要另外定义一个变量,永远指向队尾。
package queue.com;
public class MyListQueue {
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
}
}
Node front;
Node rear;
int usedSize;
//判断是否为空
public boolean isEmpty() {
return usedSize == 0;
}
// 入队(尾插)
public void offer(int data) {
Node node = new Node(data);
if (isEmpty()) {
this.front = node;
this.rear = node;
} else {
this.rear.next = node;
this.rear = node;
}
this.usedSize++;
}
//出队(从头出)
public int poll() {
int tmp = this.front.data;
this.front = this.front.next;
this.usedSize--;
return tmp;
}
//弹出队头元素
public int peek() {
return this.front.data;
}
}
顺序队列(循环队列):
为啥要把队列设置为循环的呢??空间的可利用效率达到最高!
队头:front
队尾:rear 当前可以存放数据元素的下标
因为front和rear相遇有可能是空的,也有可能是满的。因此我们规定front和rear相遇的时候队列是空的,判断为满:牺牲一定的空间,如果我们要放8个元素,放入7个元素就认为队列已经满了。如果要放第8个元素的时候,先判断(rear+1)%length是否等于front:若相等,则满。
package queue.com;
public class MyCircularQueue {
public int[] elem;
public int front;
public int rear;
public int usedSize;
public MyCircularQueue(int k) {
this.elem = new int[k+1];
this.front = 0;
this.rear = 0;
this.usedSize = 0;
}
//进队列
public boolean enQueue(int value) {
if (isFull()) {
return false;
}
this.elem[rear] = value;
this.rear = (this.rear + 1) % this.elem.length;
this.usedSize++;
return true;
}
//出队列
public boolean deQueue() {
if (isEmpty()) {
return false;
}
this.front = (this.front+1) % this.elem.length;
this.usedSize--;
return true;
}
//弹出队头元素
public int Front() {
if(isEmpty()) {
return -1;
}
return this.elem[this.front];
}
//弹出队尾元素
public int Rear() {
if(isEmpty()) {
return -1;
}
int index = this.rear == 0 ? index = this.elem.length-1 : this.rear-1;
return elem[index];
}
public boolean isEmpty() {
return this.front == this.rear;
}
public boolean isFull() {
return this.front == (this.rear+1)%this.elem.length;
}
}
Java中的队列:
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
queue.add(1); //入队列 [抛出异常]
queue.offer(1); //入队列 [返回特殊值]
queue.remove(); //出队列 [抛出异常]
queue.poll(); // 出队列 [返回特殊值]
queue.element(); //队首元素 [抛出异常]
queue.peek(); //队首元素 [返回特殊值]
}