一.什麼是隊列?
隊列(Queue)跟棧(Stack)一樣是一種線性數據結構,但是不同於棧的先入後出,隊列中的元素只能先入先出(First In First Out, 簡稱 FIFO),也就是元素只能從一端進,另一端出。
通常,隊列的出口端叫做 隊頭(front),入口端叫做 隊尾(rear);數據元素進入隊列的過程就叫做 入隊,出隊列的過程就叫做 出隊。隊列中數據元素的進出要遵從 “先進先出”的原則。
二.隊列的實現
隊列的實現有以下兩種方式:
- 順序隊列:數組來實現的隊列結構。
- 鏈式隊列:用鏈表來實現的隊列結構。
三.隊列的應用
- 實際生活中比較常見的,每次排隊在奶茶店買奶茶都應該是一個隊列。畢竟在前面的肯定先買到。
- 在大學裏,如果所有的電腦終端都被佔用了,並且由於資源是有限的,學生們必須在一個等待表上簽字,在終端上登陸時間最長的學生將會首先被強制離開,而等待時間最長的學生將是下一個被允許使用電腦的用戶。
四.數組實現單向隊列
因爲隊列的進隊和出隊是分別從隊頭和隊尾來進行的,所以需要兩個變量 front 及 rear 分別記錄隊列隊頭和隊尾的下標,front 會隨着數據出隊而改變,而 rear 則是隨着數據入隊而改變。
1.入隊
- 當數據存入隊列時,稱爲 " 入隊(addQueue) ";入隊 尾指針需要向後移,即: rear + 1。
- 這裏要注意,當隊列已經是滿的時候,是無法入隊的,即:若隊尾指針 rear 小於 隊列的最大下標 - 1,則將數據存入 rear 所指的數組元素中,否則無法存入數據。
2.出隊
- 當數據出隊時,出隊 頭指針需要向後移,即:front + 1。
五.特殊情況處理
- 隊列爲空,即 front == rear。
// 判斷隊列是否爲空
public boolean isEmptyQueue() {
return rear == front;
}
隊列是否已滿,當尾指針等於隊列最大下標 - 1時判斷爲滿,即:rear == maxSize - 1。
// 判斷隊列是否已滿
public boolean ifFullQueue() {
return rear == maxSize - 1;
}
六.代碼
import java.util.Queue;
import java.util.Scanner;
import javax.management.RuntimeOperationsException;
public class ArrayQueueDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
ArrayQueue arrayQueue = new ArrayQueue(5); // 隊列長度設置 5
char input = ' '; // 用戶輸入
boolean loop = true;
// 菜單
while (loop) {
System.out.println("s(showQueue): 打印隊列");
System.out.println("a(addQueue): 添加數據-入隊");
System.out.println("g(getQueue): 取出數據-出隊");
System.out.println("h(showFront): 查看隊頭的數據");
System.out.println("e(exit): 退出程序");
// 獲取用戶輸入的字符
input = scanner.next().charAt(0);
switch (input) {
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.printf("取出的數據爲: %d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'h':
try {
int res = arrayQueue.showHeadQueue();
System.out.printf("隊列頭的數據是: %d\n", res);
} catch (Exception e) {
System.out.println(e.getMessage());
}
break;
case 'e':
scanner.close();
loop = false;
break;
default:
break;
}
}
System.out.println("程序退出!");
}
}
// 用數組實現隊列,先創建一個 ArrayQueue類
class ArrayQueue {
private int maxSize; // 數組的最大容量
private int front; // 隊列頭部
private int rear; // 隊列尾部
private int[] arr; // 數組模擬隊列,存放數據
// 創建隊列的有參構造器
public ArrayQueue(int arrMaxSize) {
maxSize = arrMaxSize;
arr = new int[maxSize];
front = -1; // 默認指向隊列頭部的前一個位置
rear = -1; // 指向隊尾的數據(隊列的最後一個數據)
}
// 判斷隊列是否已滿
public boolean ifFullQueue() {
return rear == maxSize - 1;
}
// 判斷隊列是否爲空
public boolean isEmptyQueue() {
return rear == front;
}
public void addQueue(int n) {
// 先判斷隊列是否已經滿
if (ifFullQueue()) {
System.out.println("隊列已經滿了,不能繼續添加數據");
return;
}
rear++;
arr[rear] = n;
}
// 出隊
public int getQueue() {
// 先判斷隊列是否爲空
if (isEmptyQueue()) {
// 拋出異常
throw new RuntimeException("隊列爲空, 不能獲取數據");
}
front++;
return arr[front];
}
public void showQueue() {
// 遍歷隊列
// 以及判斷是否爲空
if (isEmptyQueue()) {
// 拋出異常
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 (isEmptyQueue()) {
// 拋出異常
throw new RuntimeException("隊列爲空,不能獲取數據");
}
return arr[front + 1];
}
}