队列
-
什么是队列?
队列是一种用于存储数据的数据结构,这一点和链表、栈相似。
定义:队列是一种只能在一端插入,在另一端删除的有序线性表。 -
在队列中插入一个元素成为入队(EnQueue),从队列中删除一个元素称为出队(Dequeue)。
-
试图对一个空的队列执行出队的操作称之为下溢(underflow)。
-
试图对一个满的队列执行入队的操作称之为溢出(overflow)。
对列的抽象数据类型
-
主要的队列操作
enQueue(int data): 在对列的队尾插入一个元素
int deQueue(): 删除并返回对首的元素 -
辅助的队列的操作
int Front() :返回对首的元素,但不删除
int QueueSize(): 返回队列中存储的元素的个数
int Empty() 指明队列中是否存储了元素 -
应用场景
操作系统根据具有相同优先级的任务到达的顺序调度任务
模拟实现世界中的队列,入售票柜台的前的队伍,或者任何需要先来先服务的场景
异步数据传输(文件输入输出、管道、套接字) -
实现方式
基于简单循环数组的实现方式
基于动态循环数组的实现方式
基于链表的实现方式
基于简单循环数组的实现方式
注意:通常使用front变量和rear变量分别表示队列中的对首元素和队尾元素
代码实现方式:
package DataStructure;
/**
* @Author by KoVaVo
* @Date 2021-05-11 19:24
* @Desc: 手写队列
* 实现方式:基于简单循环数组方式实现队列
*/
public class ArrayQueueDemo {
//对首
private int front;
//队尾
private int rear;
private int capacity;
private int [] array;
private ArrayQueueDemo(int size){
capacity = size;
front =-1;
rear = -1;
array = new int[size];
}
public static ArrayQueueDemo createQueue(int size){
return new ArrayQueueDemo(size);
}
public boolean isEmpty(){
return (front == -1);
}
public boolean isFull(){
return ((rear+1)%capacity == front);
}
public int getQueueSize(){
return ((capacity-front+rear+1)%capacity);
}
public void enQueue(int data){
if(isFull()){
//可以抛出异常
System.out.println("queue overflow");
}else {
rear=rear+1%capacity;
array[rear] = data;
if(front == -1){
front = rear;
}
}
}
public int deQueue(){
int data = 0;
if(isEmpty()){
//如果队列是空的,那么抛出异常
System.out.println("queue is empty");
}else {
data = array[front];
if(front == rear){
front = rear-1;
}else {
front = (front + 1)%capacity;
}
}
return data;
}
}
性能表现
空间复杂度(用于n次enQueue操作) | O(n) |
---|---|
enQueue()的时间复杂度 | O(1) |
deQueue()的时间复杂度 | O(1) |
isEmpty()的时间复杂度 | O(1) |
isFull()的时间复杂度 | O(1) |
getQueueSize()的时间复杂度 | O(1) |
局限性:
用于实现队列的数组的最大空间必须预先生命且不能改变,视图对一个满队列执行入队的操作会产生一个针对简单数组这种特定实现队列方式的异常。
基于动态循环数组实现队列
实现代码:
package DataStructure.Queue;
import sun.misc.Queue;
/**
* @Author by KoVaVo
* @Date 2021-05-11 21:00
* @Desc: 基于动态循环数组实现队列
*/
public class DynArrayQueue extends Queue {
//对首
private int front;
//队尾
private int rear;
private int capacity;
private int [] array;
public DynArrayQueue(){
capacity=1;
front =-1;
rear=-1;
array =new int[1];
}
public static DynArrayQueue createDynArrayQueue(){
return new DynArrayQueue();
}
@Override
public boolean isEmpty(){
return (front ==-1);
}
public boolean isFull(){
return (rear + 1)%capacity == front;
}
public int getQueueSize(){
if(front == -1){
return 0;
}
int size = ((capacity -front + rear+1)%capacity);
if(size == 0){
return capacity;
}else{
return size;
}
}
//动态的扩充数组的长度
public void resizeQueue(){
int initCapacity = capacity;
capacity *=2;
int [] oldArray=array;
array = new int[this.capacity];
for (int i = 0; i < oldArray.length; i++) {
array[i] = oldArray[i];
}
if(rear < front){
for (int i = 0; i < front; i++) {
array[i+initCapacity] = this.array[i];
array[i] = Integer.parseInt(null);
}
rear = rear+initCapacity;
}
}
//入队
public void enQueue(int data){
if(isFull()){
resizeQueue();
}
rear = (rear+1)%capacity;
array[rear] =data;
if(front == -1){
front = rear;
}
}
//出队
public int deQueue(){
int data = 0;
if(isEmpty()){
System.out.println("队列是空的");
return data;
}else{
data = array[front];
if(front == rear){
front = rear=-1;
}else{
front = (front+1)%capacity;
}
System.out.println(data);
}
return data;
}
public static void main(String[] args) {
DynArrayQueue dynArrayQueue = new DynArrayQueue();
dynArrayQueue.enQueue(1);
dynArrayQueue.enQueue(2);
dynArrayQueue.enQueue(3);
dynArrayQueue.enQueue(4);
dynArrayQueue.deQueue();
dynArrayQueue.deQueue();
dynArrayQueue.deQueue();
dynArrayQueue.deQueue();
}
}
性能:
空间复杂度(用于n次enQueue操作) | O(n) |
---|---|
enQueue()的时间复杂度 | O(1) |
deQueue()的时间复杂度 | O(1) |
getQueueSize()的时间复杂度 | O(1) ) |
isEmpty()的时间复杂度 | O(1) |
isFull()的时间复杂度 | O(1) |
基于链表实现队列
实现队列的另外一种方式是基于链表。通过在链表末端插入元素的方法实现入队的操作,用过删除链表表头的元素实现出队的操作。
伪代码实现:
package DataStructure.Queue;
import javax.xml.soap.Node;
/**
* @Author by KoVaVo
* @Date 2021-05-16 12:04
* @Desc: 基于链表实现队列
*/
public class LLQueue {
private LLNode frontNode;
private LLNode rearNode;
private LLQueue(){
this.frontNode = null;
this.rearNode = null;
}
public static LLQueue createQueue(){
return new LLQueue();
}
public boolean isEmpty(){
return (frontNode == null);
}
public void enQueue(int data){
LLNode newNode = new LLNode();
if(rearNode != null){
rearNode.setNext(newNode);
}
rearNode = newNode;
if(frontNode == null){
frontNode = rearNode;
}
}
public int deQeueue(){
int data = 0;
if(isEmpty()){
System.out.println("队列是空的");
return data;
}else{
data = frontNode.getData();
frontNode = frontNode.getNext();
}
return data;
}
}
性能分析:
空间复杂度(用于n次enQueue操作) | O(n) |
---|---|
enQueue()的时间复杂度 | O(1) |
deQueue()的时间复杂度 | O(1) |
isEmpty()的时间复杂度 | O(1) |
deleteQueue()的时间复杂度 | O(1) |