一.普通队列
首先先用数组模拟一下简单的队列。对于队列,有4个元素,一个头head,一个尾tail,一个队列的最大容量maxSize,还有一个数组int[] 模拟队列。队列的主要操作有1.向队列中添加数据;2.展示整个队列中的数据;3.取出队列的第一个数据;4.得到队列的第一个数据,不取出,只展示;5.判断队列是否为空(head == tail);6.判断队列是否已满(tail == maxSize -1)。
因为队列的输出、输入是分别从前后端来处理,因此需要两个变量 head及 tail 分别记录队列前后端的下标,head会随着数据的输出而改变,tail会随着数据的输入而改变。
代码如下:
队列
class Queue{
private int head;// 队列头
private int tail;// 队列尾
private int maxSize;// 队列的最大容量
private int[] queue;// 存放数据,模拟队列
public Queue(int maxSize){
this.maxSize = maxSize;
queue = new int[maxSize];
head = -1; // 指向队列头部,分析出 front 是指向队列头的前一个位置.
tail = -1; // 指向队列尾,指向队列尾的数据(即就是队列最后一个数据)
}
// 判断队列是否满
public boolean isFull(){
return tail == maxSize-1;
}
// 判断队列是否为空
public boolean isEmpty(){
return tail == head;
}
// 添加数据到队列中
public void addQueue(int value){
if(isFull()){
System.out.println("队列已满,无法添加数据");
return ;
}
tail = tail+1;
queue[tail] = value;
}
// 取出第一条数据
public int getQueue(){
if(isEmpty()){
throw new RuntimeException("队列为空,无法取出数据");
}
head = head+1;
return queue[head];
}
// 展示队列中的数据
public void showQueue(){
if(isEmpty()){
System.out.println("队列为空,无法取出数据");
return;
}
for(int i=0;i<queue.length;i++){
System.out.println(queue[i]+" ");
}
}
// 显示头结点的数据
public int showHead(){
if(isEmpty()){
throw new RuntimeException("队列为空");
}
return queue[head+1];
}
}
测试代码
package com.an.struct.queue;
import java.util.Scanner;
/**
* 数组模拟队列
* @author AN
* @create 2020-08-04 16:51
*/
public class ArrQueue {
public static void main(String[] args) {
Queue queue = new Queue(3);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean flag = true;
while(flag){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列中取数据");
System.out.println("h(head):查看队列头数据");
key = scanner.next().charAt(0);
switch (key){
case 's':
queue.showQueue();
break;
case 'e':
flag = false;
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'g':
try {
int value1 = queue.getQueue();
System.out.println("取出的数据为:"+value1);
break;
}catch (Exception e){
System.out.println(e.getMessage());
}
case 'h':
try {
int headValue = queue.showHead();
System.out.println("取出的头结点的数据为:"+headValue);
break;
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
}
}
二.循环队列
对于普通的队列来说,使用一次就不能再次使用,没有达到复用的效果。对这个数组使用算法,改进这个队列,成为一个环形队列。对于环形队列,和普通队列一样,也有4个元素。但是不一样的是
1.head不再指向队列头的前一个元素,应该指向队列的第一个元素,所以head初始值为head=0;
2.tail指向队列中最后一个元素的后一个位置,因为希望空出一个位置作为约定,所以队列中会空出一个位置,当maxSize为4时,队列中最大的数量为3。tail的初始值为0;
3.当队列满的时候,(tail+1)%maxSize == head;
4.当队列为空时,tail == head,和之前一样;
5.队列中的有效数据的格式为 (tail+maxSize-head)%maxSize
6.修改以下,就构成了循环队列
循环队列
// 环形队列
class CircleQueue{
private int head;
private int tail;
private int maxSize;
private int[] queue;
public CircleQueue(int maxSize){
head = 0;
tail = 0;
this.maxSize = maxSize;
queue = new int[maxSize];
}
// 判断队列是否满
public boolean isFull(){
return (tail+1)%maxSize == head;
}
// 判断队列是否为空
public boolean isEmpty(){
return tail == head;
}
// 添加数据到队列中
public void addQueue(int value){
if(isFull()){
System.out.println("队列已满,无法添加数据");
return ;
}
queue[tail] = value;
tail = (tail+1)%maxSize;
}
// 取出第一条数据
public int getQueue(){
if(isEmpty()){
throw new RuntimeException("队列为空,无法取出数据");
}
int tmp = queue[head];
head = (head+1)%maxSize;
return tmp;
}
// 展示队列中的数据
public void showQueue(){
if(isEmpty()){
System.out.println("队列为空,无法取出数据");
return;
}
for(int i=head;i<head+queueSize();i++){
System.out.println(queue[i % maxSize]+" ");
}
}
// 找出队列中的个数
public int queueSize(){
return (tail+maxSize-head)%maxSize;
}
// 显示头结点的数据
public int showHead(){
if(isEmpty()){
throw new RuntimeException("队列为空");
}
return queue[head];
}
}
测试循环队列
package com.an.struct.queue;
import java.util.Scanner;
/**
* 数组模拟环形队列
*
* @author AN
* @create 2020-08-05 14:53
*/
public class CircleArrayQueue {
public static void main(String[] args) {
CircleQueue queue = new CircleQueue(4);
char key = ' ';
Scanner scanner = new Scanner(System.in);
boolean flag = true;
while(flag){
System.out.println("s(show):显示队列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加数据到队列");
System.out.println("g(get):从队列中取数据");
System.out.println("h(head):查看队列头数据");
key = scanner.next().charAt(0);
switch (key){
case 's':
queue.showQueue();
break;
case 'e':
flag = false;
break;
case 'a':
System.out.println("输出一个数");
int value = scanner.nextInt();
queue.addQueue(value);
break;
case 'g':
try {
int value1 = queue.getQueue();
System.out.println("取出的数据为:"+value1);
break;
}catch (Exception e){
System.out.println(e.getMessage());
}
case 'h':
try {
int headValue = queue.showHead();
System.out.println("取出的头结点的数据为:"+headValue);
break;
}catch (Exception e){
System.out.println(e.getMessage());
}
}
}
}
}