【Java數據結構學習筆記之三】Java數據結構與算法之隊列(Queue)實現

  本篇是數據結構與算法的第三篇,本篇咱們未來了解一下知識點:java

  • 隊列的抽象數據類型
  • 順序隊列的設計與實現
  • 鏈式隊列的設計與實現
  • 隊列應用的簡單舉例
  • 優先隊列的設置與實現雙鏈表實現

隊列的抽象數據類型

  隊列一樣是一種特殊的線性表,其插入和刪除的操做分別在表的兩端進行,隊列的特色就是先進先出(First In First Out)。咱們把向隊列中插入元素的過程稱爲入隊(Enqueue),刪除元素的過程稱爲出隊(Dequeue)並把容許入隊的一端稱爲隊尾,容許出的的一端稱爲隊頭,沒有任何元素的隊列則稱爲空隊。其通常結構以下:算法

關於隊列的操做,咱們這裏主要實現入隊,出隊,判斷空隊列和清空隊列等操做,聲明隊列接口Queue(隊列抽象數據類型)以下:數組

 1 /**
 2 * 隊列抽象數據類型
 3 */
 4 public interface Queue<T> {
 5 
 6    /**
 7     * 返回隊列長度
 8     * @return
 9     */
10    int size();
11 
12    /**
13     * 判斷隊列是否爲空
14     * @return
15     */
16    boolean isEmpty();
17 
18    /**
19     * data 入隊,添加成功返回true,不然返回false,可擴容
20     * @param data
21     * @return
22     */
23    boolean add(T data);
24 
25    /**
26     * offer 方法可插入一個元素,這與add 方法不一樣,
27     * 該方法只能經過拋出未經檢查的異常使添加元素失敗。
28     * 而不是出現異常的狀況,例如在容量固定(有界)的隊列中
29     * NullPointerException:data==null時拋出
30     * @param data
31     * @return
32     */
33    boolean offer(T data);
34 
35    /**
36     * 返回隊頭元素,不執行刪除操做,若隊列爲空,返回null
37     * @return
38     */
39    T peek();
40 
41    /**
42     * 返回隊頭元素,不執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
43     * @return
44     */
45    T element();
46 
47    /**
48     * 出隊,執行刪除操做,返回隊頭元素,若隊列爲空,返回null
49     * @return
50     */
51    T poll();
52 
53    /**
54     * 出隊,執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
55     * @return
56     */
57    T remove();
58 
59    /**
60     * 清空隊列
61     */
62    void clearQueue();
63 }

下面咱們就來分別實現順序隊列和鏈式隊列數據結構

順序隊列的設計與實現

  關於順序隊列(底層都是利用數組做爲容器)的實現,咱們將採用順序循環隊列的結構來實現,在給出實現方案前先來分析一下爲何不直接使用順序表做爲底層容器來實現。實際上採用順序表實現隊列時,入隊操做直接執行順序表尾部插入操做,其時間複雜度爲O(1),出隊操做直接執行順序表頭部刪除操做,其時間複雜度爲O(n),主要用於移動元素,效率低,既然如此,咱們就把出隊的時間複雜度降爲O(1)便可,爲此在順序表中添加一個頭指向下標front和尾指向下標,出隊和入隊時只要改變front、rear的下標指向取值便可,此時無需移動元素,所以出隊的時間複雜度也就變爲O(1)。其過程以下圖所示異步

以上是添加front和rear下標記錄的順序表插入過程編輯器

從圖的演示過程,(a)操做時,是空隊列此時front和rear都爲-1,同時能夠發現雖然咱們經過給順序表添加front和rear變量記錄下標後使用得出隊操做的時間複雜度降爲O(1),可是卻出現了另一個嚴重的問題,那就是空間浪費,從圖中的(d)和(e)操做能夠發現,20和30出隊後,遺留下來的空間並無被從新利用,反而是空着,因此致使執行(f)操做時,出現隊列已滿的假現象,這種假現象咱們稱之爲假溢出,之因此出現這樣假溢出的現象是由於順序表隊列的存儲單元沒有重複利用機制,而解決該問題的最合適的方式就是將順序隊列設計爲循環結構,接下來咱們就經過循環順序表來實現順序隊列。
  順序循環隊列就是將順序隊列設計爲在邏輯結構上收尾相接的循環結構,這樣咱們就能夠重複利用存儲單元,其過程以下所示:ide

 

簡單分析一下:
其中採用循環結構的順序表,能夠循環利用存儲單元,所以有以下計算關係(其中size爲隊列長度):測試

//其中front、rear的下標的取值範圍是0~size-1,不會形成假溢出。
front=(front+1)%size;//隊頭下標
rear=(rear+1)%size;

front爲隊頭元素的下標,rear則指向下一個入隊元素的下標this

當front=rear時,咱們約定隊列爲空。idea

出隊操做改變front下標指向,入隊操做改變rear下標指向,size表明隊列容量。

約定隊列滿的條件爲front=(rear+1)%size,注意此時隊列中仍有一個空的位置,此處留一個空位主要用於避免與隊列空的條件front=rear相同。

隊列內部的數組可擴容,並按照原來隊列的次序複製元素數組
瞭解了隊列的實現規則後,咱們重點分析一下入隊add方法和出隊poll方法,其中入隊add方法實現以下:

/**
  * data 入隊,添加成功返回true,不然返回false,可擴容
  * @param data
  * @return
  */
 @Override
 public boolean add(T data) {
     //判斷是否滿隊
     if (this.front==(this.rear+1)%this.elementData.length){
         ensureCapacity(elementData.length*2+1);
     }
     //添加data
     elementData[this.rear]=data;
     //更新rear指向下一個空元素的位置
     this.rear=(this.rear+1)%elementData.length;
     size++;
     return true;
 }

在add方法中咱們先經過this.front==(this.rear+1)%this.elementData.length判斷隊列是否滿,在前面咱們約定過隊列滿的條件爲front=(rear+1)%size,若是隊列滿,則先經過ensureCapacity(elementData.length*2+1)擴容,該方法實現以下:

 1 /**
 2   * 擴容的方法
 3   * @param capacity
 4   */
 5  public void ensureCapacity(int capacity) {
 6      //若是須要拓展的容量比如今數組的容量還小,則無需擴容
 7      if (capacity<size)
 8          return;
 9 
10      T[] old = elementData;
11      elementData= (T[]) new Object[capacity];
12      int j=0;
13      //複製元素
14      for (int i=this.front; i!=this.rear ; i=(i+1)%old.length) {
15          elementData[j++] = old[i];
16      }
17      //恢復front,rear指向
18      this.front=0;
19      this.rear=j;
20  }

這個方法比較簡單,主要建立一個新容量的數組,並把舊數組中的元素複製到新的數組中,這裏惟一的要注意的是,判斷久數組是否複製完成的條件爲i!=this.rear,同時循環的自增條件爲i=(i+1)%old.length。擴容後直接經過rear添加新元素,最後更新rear指向下一個入隊新元素。對於出隊操做poll的實現以下:

 1 /**
 2  * 出隊,執行刪除操做,返回隊頭元素,若隊列爲空,返回null
 3  * @return
 4  */
 5 @Override
 6 public T poll() {
 7     T temp=this.elementData[this.front];
 8     this.front=(this.front+1)%this.elementData.length;
 9     size--;
10     return temp;
11 }

出隊操做相對簡單些,直接存儲要刪除元素的數據,並更新隊頭front的值,最後返回刪除元素的數據。ok~,關於循環結構的順序隊列,咱們就分析到此,最後給出循環順序隊列的實現源碼,其餘方法比較簡單,註釋也很清楚,就不過多分析了:

  1 import java.io.Serializable;
  2 import java.util.NoSuchElementException;
  3 
  4 /**
  5  * 順序隊列的實現
  6  */
  7 public class SeqQueue<T> implements Queue<T> ,Serializable {
  8 
  9 
 10     private static final long serialVersionUID = -1664818681270068094L;
 11     private static final int  DEFAULT_SIZE = 10;
 12 
 13     private T elementData[];
 14 
 15     private int front,rear;
 16 
 17     private int size;
 18 
 19 
 20     public SeqQueue(){
 21         elementData= (T[]) new Object[DEFAULT_SIZE];
 22         front=rear=0;
 23     }
 24 
 25     public SeqQueue(int capacity){
 26         elementData= (T[]) new Object[capacity];
 27         front=rear=0;
 28     }
 29 
 30     @Override
 31     public int size() {
 32 //        LinkedList
 33         return size;
 34     }
 35 
 36     @Override
 37     public boolean isEmpty() {
 38         return front==rear;
 39     }
 40 
 41     /**
 42      * data 入隊,添加成功返回true,不然返回false,可擴容
 43      * @param data
 44      * @return
 45      */
 46     @Override
 47     public boolean add(T data) {
 48         //判斷是否滿隊
 49         if (this.front==(this.rear+1)%this.elementData.length){
 50             ensureCapacity(elementData.length*2+1);
 51         }
 52         //添加data
 53         elementData[this.rear]=data;
 54         //更新rear指向下一個空元素的位置
 55         this.rear=(this.rear+1)%elementData.length;
 56         size++;
 57         return true;
 58     }
 59 
 60     /**
 61      * offer 方法可插入一個元素,這與add 方法不一樣,
 62      * 該方法只能經過拋出未經檢查的異常使添加元素失敗。
 63      * 而不是出現異常的狀況,例如在容量固定(有界)的隊列中
 64      * NullPointerException:data==null時拋出
 65      * IllegalArgumentException:隊滿,使用該方法可使Queue的容量固定
 66      * @param data
 67      * @return
 68      */
 69     @Override
 70     public boolean offer(T data) {
 71         if (data==null)
 72             throw new NullPointerException("The data can\'t be null");
 73         //隊滿拋出異常
 74         if (this.front==(this.rear+1)%this.elementData.length){
 75             throw new IllegalArgumentException("The capacity of SeqQueue has reached its maximum");
 76         }
 77 
 78         //添加data
 79         elementData[this.rear]=data;
 80         //更新rear指向下一個空元素的位置
 81         this.rear=(this.rear+1)%elementData.length;
 82         size++;
 83 
 84         return true;
 85     }
 86 
 87     /**
 88      * 返回隊頭元素,不執行刪除操做,若隊列爲空,返回null
 89      * @return
 90      */
 91     @Override
 92     public T peek() {
 93         return elementData[front];
 94     }
 95 
 96     /**
 97      * 返回隊頭元素,不執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
 98      * @return
 99      */
100     @Override
101     public T element() {
102         if(isEmpty()){
103             throw new NoSuchElementException("The SeqQueue is empty");
104         }
105         return peek();
106     }
107 
108     /**
109      * 出隊,執行刪除操做,返回隊頭元素,若隊列爲空,返回null
110      * @return
111      */
112     @Override
113     public T poll() {
114         T temp=this.elementData[this.front];
115         this.front=(this.front+1)%this.elementData.length;
116         size--;
117         return temp;
118     }
119 
120     /**
121      * 出隊,執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
122      * @return
123      */
124     @Override
125     public T remove() {
126         if (isEmpty()){
127             throw new NoSuchElementException("The SeqQueue is empty");
128         }
129         return poll();
130     }
131 
132     @Override
133     public void clearQueue() {
134         for (int i=this.front; i!=this.rear ; i=(i+1)%elementData.length) {
135             elementData[i] = null;
136         }
137         //復位
138         this.front=this.rear=0;
139         size=0;
140     }
141 
142     /**
143      * 擴容的方法
144      * @param capacity
145      */
146     public void ensureCapacity(int capacity) {
147         //若是須要拓展的容量比如今數組的容量還小,則無需擴容
148         if (capacity<size)
149             return;
150 
151         T[] old = elementData;
152         elementData= (T[]) new Object[capacity];
153         int j=0;
154         //複製元素
155         for (int i=this.front; i!=this.rear ; i=(i+1)%old.length) {
156             elementData[j++] = old[i];
157         }
158         //恢復front,rear指向
159         this.front=0;
160         this.rear=j;
161     }
162 }

鏈式隊列的設計與實現

  分析完順序隊列,咱們接着看看鏈式隊列的設計與實現,對於鏈式隊列,將使用帶頭指針front和尾指針rear的單鏈表實現,front直接指向隊頭的第一個元素,rear指向隊尾的最後一個元素,其結構以下:

  之因此選擇單鏈表(帶頭尾指針)而不採用循環雙鏈表或者雙鏈表主要是雙鏈表的空間開銷(空間複雜度,多前繼指針)相對單鏈表來講大了很多,而單鏈表只要新增頭指針和尾指針就能夠輕鬆實現常數時間內(時間複雜度爲O(1))訪問頭尾結點。下面咱們來看看如何設計鏈式隊列:

以上述的圖爲例分別設置front和rear指向隊頭結點和隊尾結點,使用單鏈表的頭尾訪問時間複雜度爲O(1)。

設置初始化空隊列,使用front=rear=null,而且約定條件front==null&&rear==null成立時,隊列爲空。

出隊操做時,若隊列不爲空獲取隊頭結點元素,並刪除隊頭結點元素,更新front指針的指向爲front=front.next

入隊操做時,使插入元素的結點在rear以後並更新rear指針指向新插入元素。

當第一個元素入隊或者最後一個元素出隊時,同時更新front指針和rear指針的指向。
這一系列過程以下圖所示:

ok~,關於鏈式隊列的設計都分析完,至於實現就比較簡單了,和以前分析過的單鏈表區別不大,所以這裏咱們直接給出實現代碼便可:

  1 import com.zejian.structures.LinkedList.singleLinked.Node;
  2 
  3 import java.io.Serializable;
  4 import java.util.*;
  5 
  6 /**
  7  * 鏈式隊列的實現
  8  */
  9 public class LinkedQueue<T> implements Queue<T> ,Serializable{
 10     private static final long serialVersionUID = 1406881264853111039L;
 11     /**
 12      * 指向隊頭和隊尾的結點
 13      * front==null&&rear==null時,隊列爲空
 14      */
 15     private Node<T> front,rear;
 16 
 17     private int size;
 18     /**
 19      * 用於控制最大容量,默認128,offer方法使用
 20      */
 21     private int maxSize=128;
 22 
 23     public LinkedQueue(){
 24         //初始化隊列
 25         this.front=this.rear=null;
 26     }
 27 
 28     @Override
 29     public int size() {
 30         return size;
 31     }
 32 
 33     public void setMaxSize(int maxSize){
 34         this.maxSize=maxSize;
 35     }
 36 
 37     @Override
 38     public boolean isEmpty() {
 39         return front==null&&rear==null;
 40     }
 41 
 42     /**
 43      * data 入隊,添加成功返回true,不然返回false,可擴容
 44      * @param data
 45      * @return
 46      */
 47     @Override
 48     public boolean add(T data) {
 49         Node<T> q=new Node<>(data,null);
 50         if (this.front==null) {//空隊列插入
 51             this.front = q;
 52         } else {//非空隊列,尾部插入
 53             this.rear.next=q;
 54         }
 55         this.rear=q;
 56         size++;
 57         return true;
 58     }
 59 
 60     /**
 61      * offer 方法可插入一個元素,這與add 方法不一樣,
 62      * 該方法只能經過拋出未經檢查的異常使添加元素失敗。
 63      * 而不是出現異常的狀況,例如在容量固定(有界)的隊列中
 64      * NullPointerException:data==null時拋出
 65      * IllegalArgumentException:隊滿,使用該方法可使Queue的容量固定
 66      * @param data
 67      * @return
 68      */
 69     @Override
 70     public boolean offer(T data) {
 71         if (data==null)
 72             throw new NullPointerException("The data can\'t be null");
 73         if (size>=maxSize)
 74             throw new IllegalArgumentException("The capacity of LinkedQueue has reached its maxSize:128");
 75 
 76         Node<T> q=new Node<>(data,null);
 77         if (this.front==null) {//空隊列插入
 78             this.front = q;
 79         } else {//非空隊列,尾部插入
 80             this.rear.next=q;
 81         }
 82         this.rear=q;
 83         size++;
 84         return false;
 85     }
 86 
 87     /**
 88      * 返回隊頭元素,不執行刪除操做,若隊列爲空,返回null
 89      * @return
 90      */
 91     @Override
 92     public T peek() {
 93         return this.isEmpty()? null:this.front.data;
 94     }
 95 
 96     /**
 97      * 返回隊頭元素,不執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
 98      * @return
 99      */
100     @Override
101     public T element() {
102         if(isEmpty()){
103             throw new NoSuchElementException("The LinkedQueue is empty");
104         }
105         return this.front.data;
106     }
107 
108     /**
109      * 出隊,執行刪除操做,返回隊頭元素,若隊列爲空,返回null
110      * @return
111      */
112     @Override
113     public T poll() {
114         if (this.isEmpty())
115             return null;
116         T x=this.front.data;
117         this.front=this.front.next;
118         if (this.front==null)
119             this.rear=null;
120         size--;
121         return x;
122     }
123 
124     /**
125      * 出隊,執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
126      * @return
127      */
128     @Override
129     public T remove() {
130         if (isEmpty()){
131             throw new NoSuchElementException("The LinkedQueue is empty");
132         }
133         T x=this.front.data;
134         this.front=this.front.next;
135         if (this.front==null)
136             this.rear=null;
137         size--;
138         return x;
139     }
140 
141     @Override
142     public void clearQueue() {
143         this.front= this.rear=null;
144         size=0;
145     }
146 }

隊列應用的簡單舉例

  1. 模擬現實世界中的隊列,如售票櫃檯的隊列以及其餘先到先服務的場景。
  2. 計算客戶在呼叫中心等待的時間。
  3. 異步數據的傳輸(文件輸入輸出、管道、嵌套字)。
  4. 操做系統中的優先級任務執行。
  5. 短信羣體發送 應用的發佈訂閱模式

優先隊列的設置與實現(雙鏈表實現)

  瞭解完循環順序隊列和鏈式隊列的實現後,咱們最後再來了解一個特殊的隊列,也就是優先隊列,在某些狀況下,有些應用系統要求不只須要按照「先來先服務」的原則進行,並且還需按照任務的重要或緊急程度進行排隊處理,此時就須要使用到優先隊列。好比在操做系統中進行進程調度管理,每一個進程都具有一個優先級值以表示進程的緊急程度,優先級高的進行先執行,同等級進程按照先進先出的原則排隊處理,此時操做系統使用的即是優先隊列管理和調度進程。
  優先級隊列也是一種特殊的數據結構,隊列中的每一個元素都有一個優先級,若每次出隊的是具備最高優先級的元素,則稱爲降序優先級隊列(老是先刪除最大的元素)。若每次出隊的是值最小的元素,則稱爲升序優先級隊列(老是先刪除最小的元素),一般狀況下咱們所說的優先隊列,通常是指降序優先級隊列。關於優先隊列的實現,可使用有序數組或者有序鏈表,也可使用二叉樹(二叉堆)實現,這裏咱們僅給出有序鏈表的簡單實現方案。而二叉樹的實現,留着後面咱們分析完樹時再給出。好~,這裏使用以前分析過的MyLikedList做爲基底,實現一個排序的SortLinkedList繼承自MyLinkedList,這裏須要注意的是排序鏈表中的T類型必須是實現了Comparable接口的類型,在SortLinkedList中主要重寫添加的add方法,插入邏輯是,經過比較元素的大小加入,而非簡單下標或尾部插入,其實現以下:

 1 import java.io.Serializable;
 2 import java.util.Iterator;
 3 import java.util.ListIterator;
 4 
 5 /**
 6  * 排序list的簡單實現
 7  */
 8 public class SortMyLinkedList<T extends Comparable<? extends T>> extends MylinkeList<T> implements Serializable {
 9 
10     private static final long serialVersionUID = -4783131709270334156L;
11 
12     @Override
13     public boolean add(T data) {
14         if(data==null)
15             throw new NullPointerException("data can\'t be null");
16 
17         Comparable cmp =data;//這裏須要轉一下類型,不然idea編輯器上檢驗不經過.
18 
19         if(this.isEmpty() || cmp.compareTo(this.last.prev.data) > 0){
20              return super.add(data);//直接尾部添加,last不帶數據的尾結點
21         }
22 
23         Node<T> p=this.first.next;
24         //查找插入點
25         while (p!=null&&cmp.compareTo(p.data)>0)
26             p=p.next;
27 
28         Node<T> q=new Node<>(p.prev,data,p);
29         p.prev.next=q;
30         p.prev=q;
31 
32         size++;
33         //記錄修改
34         modCount++;
35 
36         return true;
37     }
38 
39     /**
40      * 不根據下標插入,只根據比較大小插入
41      * @param index
42      * @param data
43      */
44     @Override
45     public void add(int index, T data) {
46         this.add(data);
47     }
48 
49 
50     /**
51      * 未實現
52      * @param index
53      * @return
54      */
55     @Override
56     public ListIterator<T> listIterator(int index) {
57         return null;
58     }
59 
60     /**
61      * 未實現
62      * @return
63      */
64     @Override
65     public Iterator<T> iterator() {
66         return null;
67     }
68 
69     //測試
70     public static void main(String[] args){
71         SortMyLinkedList<Integer> list=new SortMyLinkedList<>();
72         list.add(50);
73         list.add(40);
74         list.add(80);
75         list.add(20);
76         print(list);
77     }
78 
79     public static void print(SortMyLinkedList mylinkeList){
80         for (int i=0;i<mylinkeList.size();i++) {
81             System.out.println("i->"+mylinkeList.get(i));
82         }
83     }
84 }

接着以SortMyLinkedList爲基底實現優先隊列PriorityQueue,實現源碼以下,實現比較簡單,感受沒啥好說的:

  1 import com.zejian.structures.LinkedList.MyCollection.SortMyLinkedList;
  2 
  3 import java.io.Serializable;
  4 import java.util.NoSuchElementException;
  5 
  6 /**
  7  * 優先隊列的簡單實現,採用排序雙鏈表,T必須實現Comparable接口
  8  */
  9 public class PriorityQueue<T extends Comparable<? extends T>> implements Queue<T> ,Serializable {
 10 
 11     private static final long serialVersionUID = 8050142086009260625L;
 12 
 13     private SortMyLinkedList<T> list;//排序循環雙鏈表
 14 
 15     private boolean asc;//true表示升序,false表示降序
 16 
 17     /**
 18      * 用於控制最大容量,默認128,offer方法使用
 19      */
 20     private int maxSize=128;
 21     /**
 22      * 初始化隊列
 23      * @param asc
 24      */
 25     public PriorityQueue(boolean asc){
 26         this.list=new SortMyLinkedList<>();
 27         this.asc=asc;//默認升序
 28     }
 29 
 30     public int getMaxSize() {
 31         return maxSize;
 32     }
 33 
 34     public void setMaxSize(int maxSize) {
 35         this.maxSize = maxSize;
 36     }
 37 
 38     @Override
 39     public int size() {
 40         return list.size();
 41     }
 42 
 43     @Override
 44     public boolean isEmpty() {
 45         return list.isEmpty();
 46     }
 47 
 48     /**
 49      * data 入隊,添加成功返回true,不然返回false
 50      * @param data
 51      * @return
 52      */
 53     @Override
 54     public boolean add(T data) {
 55         return list.add(data);
 56     }
 57 
 58     /**
 59      * offer 方法可插入一個元素,這與add 方法不一樣,
 60      * 該方法只能經過拋出未經檢查的異常使添加元素失敗。
 61      * 而不是出現異常的狀況,例如在容量固定(有界)的隊列中
 62      * NullPointerException:data==null時拋出
 63      * IllegalArgumentException:隊滿,使用該方法可使Queue的容量固定
 64      * @param data
 65      * @return
 66      */
 67     @Override
 68     public boolean offer(T data) {
 69         if (data==null)
 70             throw new NullPointerException("The data can\'t be null");
 71         if (list.size()>=maxSize)
 72             throw new IllegalArgumentException("The capacity of PriorityQueue has reached its maxSize:128");
 73 
 74         return add(data);
 75     }
 76 
 77     /**
 78      * 返回隊頭元素,不執行刪除操做,若隊列爲空,返回null
 79      * @return
 80      */
 81     @Override
 82     public T peek() {
 83         if(isEmpty()){
 84             return null;
 85         }
 86         return this.asc ? this.list.get(0):this.list.get(size()-1);
 87     }
 88 
 89     /**
 90      * 返回隊頭元素,不執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
 91      * @return
 92      */
 93     @Override
 94     public T element() {
 95         if(isEmpty()){
 96             throw new NoSuchElementException("The PriorityQueue is empty");
 97         }
 98         return peek();
 99     }
100 
101     /**
102      * 出隊,執行刪除操做,返回隊頭元素,若隊列爲空,返回null
103      * @return
104      */
105     @Override
106     public T poll() {
107         if(isEmpty()){
108             return null;
109         }
110         return this.asc ? this.list.remove(0): this.list.remove(list.size()-1);
111     }
112 
113     /**
114      * 出隊,執行刪除操做,若隊列爲空,拋出異常:NoSuchElementException
115      * @return
116      */
117     @Override
118     public T remove() {
119         if (isEmpty()){
120             throw new NoSuchElementException("The PriorityQueue is empty");
121         }
122         return poll();
123     }
124 
125     @Override
126     public void clearQueue() {
127         this.list.clear();
128     }
129 
130     //測試
131     public static void main(String[] args){
132         PriorityQueue<Process> priorityQueue=new PriorityQueue<>(false);
133 
134         System.out.println("初始化隊列");
135         priorityQueue.add(new Process("進程1",10));
136         priorityQueue.add(new Process("進程2",1));
137         priorityQueue.add(new Process("進程3",8));
138         priorityQueue.add(new Process("進程4",3));
139         priorityQueue.add(new Process("進程5"));
140         System.out.println("隊列中的進程執行優先級:");
141         while (!priorityQueue.isEmpty()){
142             System.out.println("process:"+priorityQueue.poll().toString());
143         }
144 
145     }
146 
147 }
相關文章
相關標籤/搜索