队列简介
队列 是 先进先出( FIFO,First In, First Out) 的线性表。在具体应用中通常用链表或者数组来实现,用数组实现的队列叫作 顺序队列 ,用链表实现的队列叫作 链式队列 。队列只允许在后端(rear)进行插入操作也就是 入队 enqueue,在前端(front)进行删除操作也就是出队 dequeue
常见队列:单队列、循环队列
假设队列中有n个元素。
访问:O(n)//最坏情况
插入删除:O(1)//后端插入前端删除元素
单队列
单队列就是常见的队列, 每次添加元素时,都是添加到队尾。单队列又分为 顺序队列(数组实现) 和 链式队列(链表实现)。
顺序队列存在“假溢出”的问题也就是明明有位置却不能添加的情况。即队尾指针已经指向末尾,但仍旧有空余位置。
public class MyQueue {
private int maxSize ; //最大容量
private int front; //队列的头部
private int rear ; //队列的尾部
private int arr[]; //存数据的数组
//创建队列的构造器
public MyQueue(int arrmaxSize){
maxSize = arrmaxSize;
arr = new int[maxSize];
front = -1 ;
rear = -1 ;
}
//判断队列是否是满的
public boolean isFull(){
return rear == maxSize-1 ;
}
//判断队列是否为空
public boolean isEmpty(){
return rear == front ;
}
//相队列里面添加数据
public void add(int num){
if (isFull()){
System.out.println("队列已经满了,不能加入数据!");
}else {
rear++;
arr[rear] = num;
//arr[++rear] = num ;
}
}
//出队列
public int poll(){
if (isEmpty()){
throw new RuntimeException("对列为空,没有数据!");//throw完了会返回
}else{
front++;
return arr[front];
}
}
//显示队列的头部,不是取出数据
public int peek(){
if (isEmpty()){
throw new RuntimeException("对列为空,没有数据!");
}else {
return arr[front+1];
}
}
}
循环队列
循环队列解决假溢出问题的方法就是,如果rear到了数组尾部,数组前面部分还有空间的话,rear可以指向前面的位置。
顺序队列中,我们说front==rear
的时候队列为空,循环队列中则不一样,也可能为满,如上图所示。解决办法有两种:
- 可以设置一个标志变量
flag
,当front==rear
并且flag=0
的时候队列为空,当front==rear
并且flag=1
的时候队列为满。 - 队列为空的时候就是
front==rear
,队列满的时候,我们保证数组还有一个空闲的位置,rear 就指向这个空闲位置,那么判断队列是否为满的条件就是:(rear+1) % QueueSize= front
。
public class MyQueue2 {
private int maxSize ; //最大容量
private int front; //队列的头部
private int rear ; //队列的尾部
private int arr[]; //存数据的数组
//创建队列的构造器
public MyQueue2(int arrmaxSize){
maxSize = arrmaxSize;
arr = new int[maxSize];
front = 0 ;
rear = 0 ;
}
//判断队列是否是满的
public boolean isFull(){
return (rear+1)%maxSize == front ;
}
//判断队列是否为空
public boolean isEmpty(){
return rear == front ;
}
//相队列里面添加数据
public void add(int num){
if (isFull()){
System.out.println("队列已经满了,不能加入数据!");
}else {
arr[rear] = num;
rear = (rear+1)%maxSize;
}
}
public int poll(){
if (isEmpty()){
throw new RuntimeException("对列为空,没有数据!");//throw完了会返回
}else{
//1、先保存front这个变量
int value = arr[front];
//2、front往后移
front = (front+1)%maxSize;
return value;
}
}
//显示队列的长度
public int length(){
return (rear+maxSize-front)%maxSize;
}
//显示队列的头部,不是取出数据
public int peek(){
if (isEmpty()){
throw new RuntimeException("对列为空,没有数据!");
}else {
return arr[front];
}
}
}
Java中的queue
//将元素插入队列,如果队列已满,则抛出一个IIIegaISlabEepeplian异常
boolean add(E e);
//将元素插入队列,如果队列已满,返回false
boolean offer(E e);
//将队首的元素删除,队列为空则抛出异常
E remove();
//将队首的元素删除,队列为空则返回null
E poll();
//获取队首元素,但不移除,队列为空则抛出异常
E element();
//获取队首元素,但不移除,队列为空则返回null
E peek();