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]

 

posted @ 2017-04-30 11:59  远近啊  阅读(8009)  评论(2编辑  收藏  举报