環形佇列(陣列模擬)
阿新 • • 發佈:2021-01-20
CircleArrayQueue(環形佇列)
為了解決陣列模擬實現佇列遺留的缺陷,嘗試用CircleArrayQueue來優化。
環形佇列思路:
- front變數的含義,做以下調整:
- front就指向佇列的第一個元素,也就是說arr[front]就是佇列的第一個元素,front初始值為0
- rear變數的含義,做以下調整:
- rear指向佇列的最後一個元素的後一個位置,空出一個空間作為約定(一種演算法實現思路,不唯一)
- 判斷佇列為滿:
(rear + 1) % maxSize == front
- 判斷佇列為空:
front == rear
(預設初始值都為0)- 佇列中的有效資料個數:
(rear + maxSize - front) % maxsize
細節:
//建立佇列的構造器 public CircleArrayQueue(int maxSize) { this.maxSize = maxSize; arr = new int[this.maxSize]; //建立對應長度的佇列 //front & rear 預設給定的值為 0 ,所以可以省略賦值操作 }
//判斷佇列是否為滿 public boolean isFull() { return (rear +
1) % maxSize == front; }
//新增資料到佇列 public void addQueue(int num) { //判斷佇列是否為滿 if (isFull()) { System.out.println("佇列已滿不能新增有效資料!"); return; } //rear初始值為0,直接指向的就是下一個位置。所以可以直接將資料加入 arr[rear] = num; //因為要做成環形佇列,所以 rear 取模向後 ++ rear = (rear +
1) % maxSize; }
//獲取佇列中的資料,出佇列 public int getQueue() { //判斷佇列是否為空 if (isEmpty()) { //丟擲異常 throw new RuntimeException("佇列為空,無法獲取有效資料 !"); } //這裡不能直接將front返回,需要經過三步 /* * 1. 先將front 對應的資料取出給臨時變數 value * 2. 將 front 後移 (取模後++) * 3. 將臨時變數存放的資料返回 */ int value = arr[front]; front = (front + 1) % maxSize; return value; }
//顯示佇列中的有效資料 public void showQueue() { //判斷佇列是否為空 if (isEmpty()) { throw new RuntimeException("佇列為空,無法獲取到有效資料! "); } //因為添加了環形操作,所以這裡不能再fori迴圈遍歷取值了 //思路: 從 front開始向後遍歷多少個數據進行輸出列印 for (int i = front; i < front + size(); i++) { System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]); } }
//獲取佇列中的有效資料個數 ==》 用於取代靜態的arr.length public int size() { return (rear + maxSize - front) % maxSize; }
程式碼實現:
package Queue;
import java.util.Scanner;
/**
* Created with IntelliJ IDEA.
* User: Joeo8
* Time: 17:17
* Description: CircleArrayQueue
*/
public class CircleArrayQueueDemo {
//測試CircleArrayQueue
public static void main(String[] args) {
CircleArrayQueue arrayQueue = new CircleArrayQueue(4);
char key = ' '; //用於接收使用者輸入的命令
Scanner scanner = new Scanner(System.in);
boolean loop = true;
//輸入一個選單
while (loop) {
System.out.println("===========CircleArrayQueue============");
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 : 檢視佇列頭資料");
System.out.println("===========CircleArrayQueue============");
key = scanner.next().charAt(0); //接收使用者輸入命令
switch (key) {
case 's': //顯示佇列
try {
arrayQueue.showQueue();
} catch (Exception e) {
e.printStackTrace();
}
break;
case 'e': //退出系統
scanner.close();
loop = false;
break;
case 'a': //向佇列新增資料
try {
System.out.println("請輸入要新增的資料");
int num = scanner.nextInt();
arrayQueue.addQueue(num);
} catch (Exception e) {
e.printStackTrace();
}
break;
case 'g': //獲取佇列中的資料
try {
int res = arrayQueue.getQueue();
System.out.printf("取出的資料是\t%d \n", res);
} catch (Exception e) {
e.printStackTrace();
}
break;
case 'h': //檢視佇列的頭資料
try {
int head = arrayQueue.headQueue();
System.out.printf("佇列的頭資料是\t%d\n",head);
} catch (Exception e) {
e.printStackTrace();
}
break;
default:
break;
}
}
System.out.println("佇列退出!");
}
}
class CircleArrayQueue {
private int maxSize; //表示陣列的最大容量
private int front; //front做調整,指向佇列中的第一個元素,預設初始值為0
private int rear; //rear做調整,約定指向最後一個元素的後一個位置,預設初始值為0
private int[] arr; //該陣列用於存放資料,模擬佇列
//建立佇列的構造器
public CircleArrayQueue(int maxSize) {
this.maxSize = maxSize;
arr = new int[this.maxSize]; //建立對應長度的佇列
//front & rear 預設給定的值為 0 ,所以可以省略賦值操作
}
//判斷佇列是否為滿
public boolean isFull() {
return (rear + 1) % maxSize == front;
}
//判斷佇列是否為空
public boolean isEmpty() {
return front == rear;
}
//新增資料到佇列
public void addQueue(int num) {
//判斷佇列是否為滿
if (isFull()) {
System.out.println("佇列已滿不能新增有效資料!");
return;
}
//rear初始值為0,直接指向的就是下一個位置。所以可以直接將資料加入
arr[rear] = num;
//因為要做成環形佇列,所以 rear 取模向後 ++
rear = (rear + 1) % maxSize;
}
//獲取佇列中的資料,出佇列
public int getQueue() {
//判斷佇列是否為空
if (isEmpty()) {
//丟擲異常
throw new RuntimeException("佇列為空,無法獲取有效資料 !");
}
//這裡不能直接將front返回,需要經過三步
/*
* 1. 先將front 對應的資料取出給臨時變數 value
* 2. 將 front 後移 (取模後++)
* 3. 將臨時變數存放的資料返回
*/
int value = arr[front];
front = (front + 1) % maxSize;
return value;
}
//顯示佇列中的有效資料
public void showQueue() {
//判斷佇列是否為空
if (isEmpty()) {
throw new RuntimeException("佇列為空,無法獲取到有效資料! ");
}
//因為添加了環形操作,所以這裡不能再fori迴圈遍歷取值了
//思路: 從 front開始向後遍歷多少個數據進行輸出列印
for (int i = front; i < front + size(); i++) {
System.out.printf("arr[%d]=%d\n", i % maxSize, arr[i % maxSize]);
}
}
//獲取佇列中的有效資料個數 ==》 用於取代靜態的arr.length
public int size() {
return (rear + maxSize - front) % maxSize;
}
//顯示佇列的頭元素(只是顯示,不是取出)
public int headQueue() {
//判斷佇列是否為空
if (isEmpty()) {
throw new RuntimeException("佇列為空,無法獲取頭元素!");
}
return arr[front];
}
}
Output:
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
java.lang.RuntimeException: 佇列為空,無法獲取到有效資料!
at Queue.CircleArrayQueue.showQueue(CircleArrayQueueDemo.java:130)
at Queue.CircleArrayQueueDemo.main(CircleArrayQueueDemo.java:29)
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
a
請輸入要新增的資料
10
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[0]=10
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
a
請輸入要新增的資料
20
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[0]=10
arr[1]=20
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
a
請輸入要新增的資料
30
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[0]=10
arr[1]=20
arr[2]=30
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
a
請輸入要新增的資料
40
佇列已滿不能新增有效資料!
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[0]=10
arr[1]=20
arr[2]=30
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
h
佇列的頭資料是 10
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
g
取出的資料是 10
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[1]=20
arr[2]=30
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
a
請輸入要新增的資料
40
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[1]=20
arr[2]=30
arr[3]=40
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
h
佇列的頭資料是 20
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
g
取出的資料是 20
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
a
請輸入要新增的資料
50
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
s
arr[2]=30
arr[3]=40
arr[0]=50
===========CircleArrayQueue============
s --> show : 顯示佇列
e --> exit : 退出系統
a --> add : 新增資料到佇列
g --> get : 從佇列中取出資料
h --> head : 檢視佇列頭資料
===========CircleArrayQueue============
e
佇列退出!
Process finished with exit code 0