數據結構(3):隊列的原理和實現

  • 2019 年 10 月 3 日
  • 筆記

完整程式碼拉到最底下

一、介紹

隊列顧名思義就像我們生活中排隊一樣,先進先出。

image

如上圖所示,25、16、5、9依次在隊列中,按照順序拿出的數據也分別是25、26、5、9。

二、實現過程及思路

底層使用數組來實現,實現的功能有插入數據到隊尾、移除隊首數據、查看隊首數據、判斷隊列是否為空、判斷隊列是否存滿。

將隊列的元素存儲在數組的某個區間內,隊列在數組中是連續的,所以使用變數標記隊列在數組中的位置。

1、編寫類及屬性

我們可以使用elements變數標記隊列中元素的數量,使用front變數標記隊首元素在數組的索引,end變數標記隊尾元素在數組中的索引。

image

public class MyQueue {        private Object[] arr;//存放隊列元素的數組      private int elements;//隊列元素數量      private int front;//隊頭元素在數組中的索引      private int end;//隊尾元素在數組中的索引          public MyQueue() {          arr = new Object[10];          elements = 0;          front = 0;          end = -1;      }        public MyQueue(int maxSize) {          arr = new Object[maxSize];          elements = 0;          front = 0;          end = -1;      }  }

2、隊列是否為空

標記隊列元數量的變數 elements 為 0 即為空

public boolean isEmpty() {      return elements == 0;  }

3、隊列是否已經滿了

隊列元素個數與數組的長度相等即為滿

public boolean isFull() {      return elements == arr.length;  }

4、獲取隊頭元素

獲取數組中索引為 front的元素

public Object peek() {      return arr[front];  }

5、移除隊首元素

每次都是移除數組中索引為 front 的元素,下一個元素就變成了隊首,即front+1,隊列元素個數elements-1。共有三種情況要考慮,如果隊列已經空了就無須做任何操作,如果已經是最後一個元素,直接將標記位置的變數重置即可,其他情況正常操作。

public Object remove() {      if (isEmpty()) {          throw new RuntimeException("隊列已經是空的,放心使用吧");      }      Object value = arr[front++];      //如果已經是最後一個元素了,將指針重置即可      if (elements == 1) {          end = -1;          front = 0;          elements = 0;      } else {          elements--;      }      return value;  }

6、插入

我們編寫一個持續可用的隊列,所以要考慮到以下情況。

(1)存儲隊列的數組滿了(隊列滿了),這個好理解,滿了就無法向隊尾加入元素了。

(2)因為隊列在數組中是連續的,如果隊列的元素在數組中最後,需要將元素從隊首到隊尾移到數組中第一位,也就是將後面的位置空出來(參考下圖)。

public void insert(Object value) {      //檢測隊列是否已經滿了      if (isFull()) {          throw new RuntimeException("隊列內元素已達到設定長度");      }        //如果後面沒有空位置,將餘下元素放到數組的頭      if (elements > 1 && end == arr.length - 1) {          int i = 0;          for (; i < elements; i++, front++) {              arr[i] = arr[front];          }          front = 0;          end = i-1;      }      //其他情況正常向後添加元素      arr[++end] = value;      elements++;  }

7、測試

public static void main(String[] args) {      MyQueue queue = new MyQueue(4);      queue.insert(11);      queue.insert(12);      queue.insert(13);      queue.insert(14);        queue.remove();      queue.remove();      queue.insert(16);      //queue.remove();      //queue.remove();        //queue.insert(19);      //queue.insert(20);      queue.remove();        queue.remove();        queue.insert(21);      queue.insert(22);        while (!queue.isEmpty()) {          System.out.println(queue.remove());      }  }

三、完整程式碼

package com.jikedaquan.datastruct;    public class MyQueue {      private Object[] arr;      private int elements;//隊列元素數量      private int front;//隊頭元素在數組中的索引      private int end;//隊尾元素在數組中的索引        public MyQueue() {          arr = new Object[10];          elements = 0;          front = 0;          end = -1;      }        public MyQueue(int maxSize) {          arr = new Object[maxSize];          elements = 0;          front = 0;          end = -1;      }        //從隊尾插入      public void insert(Object value) {          //檢測隊列是否已經滿了          if (isFull()) {              throw new RuntimeException("隊列內元素已達到設定長度");          }            //如果後面沒有空位置,將餘下元素放到數組的頭          if (elements > 1 && end == arr.length - 1) {              int i = 0;              for (; i < elements; i++, front++) {                  arr[i] = arr[front];              }              front = 0;              end = i-1;          }          arr[++end] = value;          elements++;        }        //刪除數據,從隊頭刪除      public Object remove() {          if (isEmpty()) {              throw new RuntimeException("隊列已經是空的,放心使用吧");          }          Object value = arr[front++];          //如果已經是最後一個元素了,將指針重置即可          if (elements == 1) {              end = -1;              front = 0;              elements = 0;          } else {              elements--;          }          return value;      }        //查看數據,從隊頭查看      public Object peek() {          return arr[front];      }        //判斷是否為空      public boolean isEmpty() {          return elements == 0;      }        public boolean isFull() {          return elements == arr.length;      }        public static void main(String[] args) {          MyQueue queue = new MyQueue(4);          queue.insert(11);          queue.insert(12);          queue.insert(13);          queue.insert(14);            queue.remove();          queue.remove();          queue.insert(16);  //        queue.remove();  //        queue.remove();    //        queue.insert(19);  //        queue.insert(20);          queue.remove();            queue.remove();            queue.insert(21);          queue.insert(22);            while (!queue.isEmpty()) {              System.out.println(queue.remove());          }      }  }