1. 程式人生 > 其它 >環形佇列(陣列模擬)

環形佇列(陣列模擬)

技術標籤:Data structure佇列演算法資料結構

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