结构:
front:随着数据输出而改变 (输出:+)
rear:随着数据输入而改变 (输入:+)
实现:数组或链表
数据存入队列(addQueue)的思路:
尾指针rear+1
若rear小于maxSize-1,则将数据存入rear所指的数组位置中
若rear=maxSize,则队列满
Java封装的Queue类的直接使用:
因为LinkedList类继承实现了Queue接口,创建LinkedList类的对象后,可以上溯到Queue,成为一个Queue对象。因此我们一般用LinkedList来实现Queue!
此时只能用Queue的方法(因为LinkedList是在此基础上进一步封装的,有些方法Queue不能用)
Queue queue = new LinkedList();
代码举例:
package queue;
import java.util.LinkedList;
import java.util.Queue;
public class QueueTest {
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(10);
q.offer(20);
q.offer(30);
q.offer(40);
System.out.println("是否包含:"+q.contains(10));
System.out.println("队列遍历:");
for (Integer i: q) {
System.out.println(i);
}
System.out.println("出队列元素:"+q.poll());
System.out.println("队列头部元素:"+q.peek());
}
}
一、单队列
package queue;
//数组模拟队列
public class ArrayQueueDemo {
public static void main(String[] args) {
ArrayQueue aq = new ArrayQueue(5);
aq.addQueue(10);
aq.addQueue(20);
aq.addQueue(30);
aq.addQueue(40);
aq.addQueue(50);
System.out.println("取出的数据为:"+aq.getQueue());
System.out.println("取出的数据为:"+aq.getQueue());
System.out.println("现有数据为:");
aq.showQueue();
}
}
//编写数组模拟队列的类
class ArrayQueue{
private int maxSize;
private int front;
private int rear;
private int[] arr;//存放数据,模拟队列
public ArrayQueue(int maxSize) {//构造器
this.maxSize = maxSize;//数组大小等于传进来的数
arr = new int[maxSize];//需要根据传参来初始化数组
front = -1;
rear = -1;//指向队尾数据,
}
//判断队列是否满
public boolean isFull() {
return rear == maxSize - 1;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;//指
}
//添加数据到队列
public void addQueue(int n) {
if(isFull()) {
System.out.println("队列满!");
return;
}
rear++;//rear如果从0开始,那就放在添加元素操作之后
arr[rear] = n;
}
//获取队列的数据,出队列
public int getQueue() {
if(isEmpty()) {
throw new RuntimeException("队列空!");//throw本身也会return
}
front++;
return arr[front];
}
//显示队列的所有数据
public void showQueue() {//展示是不需要返回值的
if(isEmpty()) {
System.out.println("队列为空!");
return;
}
for (int i = front+1; i < rear+1; i++) {
System.out.println(arr[i]);
}
}
}
单队列会导致在元素出队列后,队列的空间无法再次被使用,即:**无法复用数组!**因为都是从队列尾rear进队列,从队列头front出队列。
因此要引入——环形队列(循环队列)。
二、环形队列
数组模拟环形队列思路分析:
1.front为指向队列的第一个元素的指针,front初始值为0;
2.rear为指向队列的最后一个元素的后一个位置的指针(因为希望空出一个空间作为约定);rear初始值也为0;
3.队列满的条件:(rear+1)%maxSize = front;
4.队列空的条件:rear = front
5.队列中的有效数据个数:(rear-front+maxSize)%maxsize
- 空队列时,rear=front=0;
- 插入一个元素:front=0,rear=1,数据放在0处;
- 满队列时:front=0,rear=7;
——插入数据到队列:rear = rear+1; 数据出队列:front = front + 1;
【例题】
删除:front+1=3+1=4,插入:rear+2=2
package queue;
public class CircleQueueDemo {
public static void main(String[] args) {
CircleQueue cq = new CircleQueue(5);
cq.addQueue(10);
cq.addQueue(20);
cq.addQueue(30);
cq.addQueue(40);
cq.addQueue(50);//其实总共能插入4个
System.out.println("取出的数据为:"+cq.getQueue());
System.out.println("取出的数据为:"+cq.getQueue());
System.out.println("队列头数据:");
cq.headQueue();
System.out.println("现有数据为:");
cq.showQueue();
}
}
//编写数组模拟环形队列的类
class CircleQueue{
private int front;
private int rear;
private int maxSize;
private int[] arr;
//构造器
public CircleQueue(int maxSize){
this.maxSize = maxSize;
arr = new int[maxSize];
front = 0;
rear = 0;
}
//判断队列是否满
public boolean isFull() {
return (rear+1) % maxSize == front;
}
//判断队列是否为空
public boolean isEmpty() {
return rear == front;//rear在最后一个元素的后面一个位置
}
//添加数据到队列
public void addQueue(int n) {
if(isFull()) {
System.out.println("队列满!");
return;
}
arr[rear] = n;
rear = (rear+1) % maxSize;//需要取模
}
//出队列
public int getQueue() {
if(isEmpty()) {
throw new RuntimeException("队列空!");
}
int value = arr[front];//因为return后方法直接结束了,所以需要先用一个变量临时保存
front = (front + 1) % maxSize;
return value;
}
//显示队列
public void showQueue() {
if(isEmpty()) {
System.out.println("队列空!");
return;
}
for(int i=front; i<front+size();i++) {
System.out.println(arr[i]);
}
}
//有效数据个数
public int size() {
return (rear - front + maxSize) % maxSize;
}
//显示队列头数据
public int headQueue() {
if(isEmpty()) {
throw new RuntimeException("队列空!");
}
return arr[front];
}
}