Java隊列存儲結構及實現


一、隊列(Queue)

隊列是一種特殊的線性表,它只允許在表的前段(front)進行刪除操作,只允許在表的后端(rear)進行插入操作。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。

對於一個隊列來說,每個元素總是從隊列的rear端進入隊列,然后等待該元素之前的所有元素出隊之后,當前元素才能出對,遵循先進先出(FIFO)原則。

如果隊列中不包含任何元素,該隊列就被稱為空隊列。

Java提供了一個Queue接口,並為該接口提供了眾多的實現類:ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、PriorityQueue、ConcurrentLinkedQueue和SynchronousQueue。

其中常用的是:ArrayBlockingQueue、LinkedBlockingQueue和CurrentLinkedQueue,它們都是線程安全的隊列。LinkedBlockingQueue隊列的吞吐量通常比ArrayBlockingQueue隊列高,但在大多數並發應用程序中,LinkedBlockingQueue的性能要低。

除了LinkedBlockingQueue隊列之外,JDK還提供了另外一種鏈隊列ConcurrentLinkedQueue,它基於一種先進的、無等待(wait-free)隊列算法實現。

二、順序隊列存儲結構的實現

  1 package com.ietree.basic.datastructure.queue;
  2 
  3 import java.util.Arrays;
  4 
  5 /**
  6  * Created by ietree
  7  * 2017/4/29
  8  */
  9 public class SequenceQueue<T> {
 10 
 11     private int DEFAULT_SIZE = 10;
 12     // 保存數組的長度
 13     private int capacity;
 14     // 定義一個數組用於保存順序隊列的元素
 15     private Object[] elementData;
 16     // 保存順序隊列中元素的當前個數
 17     private int front = 0;
 18     private int rear = 0;
 19 
 20     // 以默認數組長度創建空順序隊列
 21     public SequenceQueue() {
 22 
 23         capacity = DEFAULT_SIZE;
 24         elementData = new Object[capacity];
 25 
 26     }
 27 
 28     // 以一個初始化元素來創建順序隊列
 29     public SequenceQueue(T element) {
 30 
 31         this();
 32         elementData[0] = element;
 33         rear++;
 34 
 35     }
 36 
 37     /**
 38      * 以指定長度的數組來創建順序線性表
 39      *
 40      * @param element  指定順序隊列中第一個元素
 41      * @param initSize 指定順序隊列底層數組的長度
 42      */
 43     public SequenceQueue(T element, int initSize) {
 44 
 45         this.capacity = initSize;
 46         elementData = new Object[capacity];
 47         elementData[0] = element;
 48         rear++;
 49     }
 50 
 51     /**
 52      * 獲取順序隊列的大小
 53      *
 54      * @return 順序隊列的大小值
 55      */
 56     public int length() {
 57 
 58         return rear - front;
 59 
 60     }
 61 
 62     /**
 63      * 插入隊列
 64      *
 65      * @param element 入隊列的元素
 66      */
 67     public void add(T element) {
 68 
 69         if (rear > capacity - 1) {
 70             throw new IndexOutOfBoundsException("隊列已滿異常");
 71         }
 72         elementData[rear++] = element;
 73 
 74     }
 75 
 76     /**
 77      * 移除隊列
 78      *
 79      * @return 出隊列的元素
 80      */
 81     public T remove() {
 82 
 83         if (empty()) {
 84             throw new IndexOutOfBoundsException("空隊列異常");
 85         }
 86 
 87         // 保留隊列的rear端的元素的值
 88         T oldValue = (T) elementData[front];
 89         // 釋放隊列頂元素
 90         elementData[front++] = null;
 91         return oldValue;
 92 
 93     }
 94 
 95     // 返回隊列頂元素,但不刪除隊列頂元素
 96     public T element() {
 97 
 98         if (empty()) {
 99             throw new IndexOutOfBoundsException("空隊列異常");
100         }
101         return (T) elementData[front];
102 
103     }
104 
105     // 判斷順序隊列是否為空
106     public boolean empty() {
107 
108         return rear == front;
109 
110     }
111 
112     // 清空順序隊列
113     public void clear() {
114 
115         // 將底層數組所有元素賦值為null
116         Arrays.fill(elementData, null);
117         front = 0;
118         rear = 0;
119 
120     }
121 
122     public String toString() {
123 
124         if (empty()) {
125 
126             return "[]";
127 
128         } else {
129 
130             StringBuilder sb = new StringBuilder("[");
131             for (int i = front; i < rear; i++) {
132                 sb.append(elementData[i].toString() + ", ");
133             }
134             int len = sb.length();
135             return sb.delete(len - 2, len).append("]").toString();
136         }
137 
138     }
139 
140 }

測試類:

 1 package com.ietree.basic.datastructure.queue;
 2 
 3 /**
 4  * Created by ietree
 5  * 2017/4/30
 6  */
 7 public class SequenceQueueTest {
 8 
 9     public static void main(String[] args) {
10 
11         SequenceQueue<String> queue = new SequenceQueue<String>();
12         // 依次將4個元素加入到隊列中
13         queue.add("aaaa");
14         queue.add("bbbb");
15         queue.add("cccc");
16         queue.add("dddd");
17         System.out.println(queue);
18 
19         System.out.println("訪問隊列的front端元素:" + queue.element());
20 
21         System.out.println("第一次彈出隊列的front端元素:" + queue.remove());
22 
23         System.out.println("第二次彈出隊列的front端元素:" + queue.remove());
24 
25         System.out.println("兩次remove之后的隊列:" + queue);
26     }
27 
28 }

程序輸出:

[dddd, cccc, bbbb, aaaa]
訪問棧頂元素:dddd
第一次彈出棧頂元素:dddd
第二次彈出棧頂元素:cccc
兩次pop之后的棧:[bbbb, aaaa]

三、隊列的鏈式存儲結構實現

  1 package com.ietree.basic.datastructure.queue;
  2 
  3 /**
  4  * Created by ietree
  5  * 2017/4/30
  6  */
  7 public class LinkQueue<T> {
  8 
  9     // 定義一個內部類Node,Node實例代表鏈隊列的節點
 10     private class Node {
 11 
 12         // 保存節點的數據
 13         private T data;
 14         // 指向下個節點的引用
 15         private Node next;
 16 
 17         // 無參構造器
 18         public Node() {
 19         }
 20 
 21         // 初始化全部屬性的構造器
 22         public Node(T data, Node next) {
 23 
 24             this.data = data;
 25             this.next = next;
 26 
 27         }
 28 
 29     }
 30 
 31     // 保存該鏈隊列的頭節點
 32     private Node front;
 33     // 保存該鏈隊列的尾節點
 34     private Node rear;
 35     // 保存該鏈隊列中已包含的節點數
 36     private int size;
 37 
 38     // 創建空鏈隊列
 39     public LinkQueue() {
 40         // 空鏈隊列,front和rear的值都為null
 41         front = null;
 42         rear = null;
 43     }
 44 
 45     // 以指定數據元素來創建鏈隊列,該鏈隊列只有一個元素
 46     public LinkQueue(T element) {
 47 
 48         front = new Node(element, null);
 49         // 只有一個節點,front、rear都是指向該節點
 50         rear = front;
 51         size++;
 52 
 53     }
 54 
 55     // 返回鏈隊列的長度
 56     public int length() {
 57 
 58         return size;
 59 
 60     }
 61 
 62     // 將新元素加入隊列
 63     public void add(T element) {
 64         // 如果該鏈隊列還是空鏈隊列
 65         if (front == null) {
 66             front = new Node(element, null);
 67             // 只有一個節點,front、rear都是指向該節點
 68             rear = front;
 69         } else {
 70             // 創建新節點
 71             Node newNode = new Node(element, null);
 72             // 讓尾節點的next指向新增的節點
 73             rear.next = newNode;
 74             rear = newNode;
 75         }
 76         size++;
 77     }
 78 
 79     // 刪除隊列front端的元素
 80     public T remove() {
 81 
 82         Node oldfront = front;
 83         // 讓front引用指向原隊列頂元素的下一個元素
 84         front = front.next;
 85         // 釋放原隊列頂元素的next引用
 86         oldfront.next = null;
 87         size--;
 88         return oldfront.data;
 89 
 90     }
 91 
 92     // 訪問隊列頂元素,但不刪除隊列頂元素
 93     public T element() {
 94 
 95         return rear.data;
 96 
 97     }
 98 
 99     // 判斷鏈隊列是否為空隊列
100     public boolean empty() {
101 
102         return size == 0;
103 
104     }
105 
106     // 請空鏈隊列
107     public void clear() {
108         // 將front、rear兩個節點賦為null
109         front = null;
110         rear = null;
111         size = 0;
112     }
113 
114     public String toString() {
115 
116         // 鏈隊列為空隊列時
117         if (empty()) {
118             return "[]";
119         } else {
120             StringBuilder sb = new StringBuilder("[");
121             for (Node current = front; current != null; current = current.next) {
122                 sb.append(current.data.toString() + ", ");
123             }
124             int len = sb.length();
125             return sb.delete(len - 2, len).append("]").toString();
126         }
127 
128     }
129 
130 }

測試類:

 1 package com.ietree.basic.datastructure.queue;
 2 
 3 /**
 4  * Created by ietree
 5  * 2017/4/30
 6  */
 7 public class LinkQueueTest {
 8 
 9     public static void main(String[] args) {
10 
11         LinkQueue<String> queue = new LinkQueue<String>("aaaa");
12         // 依次將4個元素加入到隊列中
13         queue.add("bbbb");
14         queue.add("cccc");
15         queue.add("dddd");
16         System.out.println(queue);
17 
18         // 刪除一個元素后
19         queue.remove();
20         System.out.println("刪除一個元素后的隊列:" + queue);
21 
22         // 再添加一個元素
23         queue.add("eeee");
24         System.out.println("再次添加元素后的隊列:" + queue);
25 
26     }
27 
28 }

程序輸出:

[aaaa, bbbb, cccc, dddd]
刪除一個元素后的隊列:[bbbb, cccc, dddd]
再次添加元素后的隊列:[bbbb, cccc, dddd, eeee]

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM