隊列
隊列是一種特殊的線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,隊列是一種操作受限制的線性表,隊列又稱爲先進先出(FIFO—first in first out)線性表。
進行插入操作的端稱爲隊尾,進行刪除操作的端稱爲隊頭
常說的隊列是指單向隊列:
Java實現單向隊列
通過操作尾指針rear、頭指針front、數組可以模擬單向隊列
- ArrayQueue構造器:初始化數組,頭、尾指針都爲0
- 頭指針指向隊列第一個元素
- 尾指針指向隊列最後一個元素後一位
- isFull:
rear == maxSize
判斷隊列是否滿 - isEmpty:
rear == front
判斷隊列是否爲空 - addQueue:添加數據到隊尾,然後後移尾指針
- getQueue:獲得隊列頭的數據,頭指針後移
- showQueue:遍歷打印所有數據
- showHeadQueue:打印隊首數據
package com.company.queue;
import java.util.Scanner;
/**
* @author zfk
* 使用數組模擬隊列
*/
public class ArrayQueueDemo {
/**
* @param args
* 測試
*/
public static void main(String[] args) {
ArrayQueue arrayQueue = new ArrayQueue(3);
char key = ' ';
boolean loop = true;
Scanner scanner = new Scanner(System.in);
System.out.println("s(show):顯示隊列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加數據到隊列");
System.out.println("g(get):從隊列取出數據");
System.out.println("h(showHead):顯示隊列頭數據");
System.out.println("============================");
while (loop){
key = scanner.next().charAt(0);
switch (key){
//顯示隊列
case 's':
arrayQueue.showQueue();
break;
// 添加數據到隊列
case 'a':
System.out.println("需要添加的數:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
//從隊列取出數據
case 'g':
try {
int res = arrayQueue.getQueue();
System.out.println("取出的數據是:" + res);
}
catch (Exception e){
System.out.println(e.getMessage());
}
break;
//顯示隊列頭數據
case 'h':
try {
int head = arrayQueue.showHeadQueue();
System.out.println("取出的隊列頭數據是:" + head);
}
catch (Exception e){
System.out.println(e.getMessage());
}
break;
//退出程序
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
}
}
class ArrayQueue{
//表示數組最大容量
private int maxSize;
//隊列頭
private int front;
//隊列尾
private int rear;
//數組存放數據,模擬隊列
private int[] arr;
//創建隊列構造器
public ArrayQueue(int arrMaxSize){
this.maxSize = arrMaxSize;
this.arr = new int[maxSize];
//指向隊列頭部,第一個數據
front = 0;
//指向隊列尾,隊列最後一個數據後一位
rear = 0;
}
//判斷隊列是否滿
public boolean isFull(){
return rear == maxSize;
}
//判斷隊列是否爲空
public boolean isEmpty(){
return rear == front;
}
//添加數據到隊列
public void addQueue(int n){
//判斷是否滿
if (isFull()){
System.out.println("隊列已滿,不能加入數據");
return;
}
arr[rear] = n;
//隊尾後移
rear++;
}
//獲取隊列數據,獲得隊列頭數據
public int getQueue(){
//判斷隊列是否爲空
if (isEmpty()){
throw new RuntimeException("隊列空,不能取數據");
}
int value = arr[front];
//front後移
front++;
return value;
}
//顯示隊列的所有數據
public void showQueue(){
//判斷是否爲空
if (isEmpty()){
System.out.println("隊列空,沒有數據");
return;
}
//遍歷
for (int i = 0;i < arr.length;i++){
System.out.printf("arr[%d] = %d \n",i,arr[i]);
}
}
//顯示隊列的頭數據
public int showHeadQueue(){
//判斷是否爲空
if (isEmpty()){
throw new RuntimeException("隊列爲空,沒有數據");
}
return arr[front];
}
}
循環隊列
前面單向隊列缺點在與“假溢出”
當兩個指針都指向隊尾後,無法插入數據
解決辦法,設置循環隊列
循環隊列,邏輯上將數組元素q[0]與q[MAX-1]連接(實際並沒有這樣的硬件)
隊首指針指向隊列第一個元素
隊尾指針指向隊列最後一個元素後一位
在循環隊列中,當隊列爲空時,有front=rear,而當所有隊列空間全佔滿時,也有front=rear,所以爲了區別這兩種情況
設置循環隊列時,特意留一個空存儲單元
即當隊列滿時,是這種情況:
Java實現循環隊列
循環隊列是對單向隊列進行了一定的改變
判斷爲空、滿、改變rear、front指針的位置使用取模的方式:rear = (rear + 1) % maxSize
,當指針指向空存儲單元,在進一位就回到0
例如:maxSize=4,當rear=3,判斷空時,4 % 4 = 0,即到隊列首位
package com.company.queue;
import java.util.Scanner;
/**
* @author zfk
* 循環隊列
*/
public class CircleArrayQueueDemo {
/**
* @param args
* 測試
*/
public static void main(String[] args) {
CircleArrayQueue arrayQueue = new CircleArrayQueue(4);
char key = ' ';
boolean loop = true;
Scanner scanner = new Scanner(System.in);
System.out.println("s(show):顯示隊列");
System.out.println("e(exit):退出程序");
System.out.println("a(add):添加數據到隊列");
System.out.println("g(get):從隊列取出數據");
System.out.println("h(showHead):顯示隊列頭數據");
System.out.println("============================");
while (loop){
key = scanner.next().charAt(0);
switch (key){
//顯示隊列
case 's':
arrayQueue.showQueue();
break;
// 添加數據到隊列
case 'a':
System.out.println("需要添加的數:");
int value = scanner.nextInt();
arrayQueue.addQueue(value);
break;
//從隊列取出數據
case 'g':
try {
int res = arrayQueue.getQueue();
System.out.println("取出的數據是:" + res);
}
catch (Exception e){
System.out.println(e.getMessage());
}
break;
//顯示隊列頭數據
case 'h':
try {
int head = arrayQueue.showHeadQueue();
System.out.println("取出的隊列頭數據是:" + head);
}
catch (Exception e){
System.out.println(e.getMessage());
}
break;
//退出程序
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
}
}
class CircleArrayQueue{
//表示數組最大容量
private int maxSize;
//隊列頭,指向隊列第一個元素
private int front;
//隊列尾,指向最後一個元素的後一個位置
private int rear;
//數組存放數據,模擬隊列
private int[] arr;
//創建隊列構造器
public CircleArrayQueue(int arrMaxSize){
this.maxSize = arrMaxSize;
this.arr = new int[maxSize];
}
//判斷隊列是否滿
public boolean isFull(){
return ( rear + 1) % maxSize == front;
}
//判斷隊列是否爲空
public boolean isEmpty(){
return rear == front;
}
//添加數據到隊列
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];
//front後移,考慮取模
front = (front + 1) % maxSize;
return value;
}
//顯示隊列的所有數據
public void showQueue(){
//判斷是否爲空
if (isEmpty()){
System.out.println("隊列空,沒有數據");
return;
}
//從front開始遍歷
for (int i = front;i < front + size();i++){
System.out.printf("arr[%d] = %d \n", i % maxSize,arr[i % maxSize]);
}
}
//取出當前隊列有效數據的個數
public int size(){
return (rear + maxSize - front) % maxSize;
}
//顯示隊列的頭數據
public int showHeadQueue(){
//判斷是否爲空
if (isEmpty()){
throw new RuntimeException("隊列爲空,沒有數據");
}
return arr[front];
}
}