Java實現佇列——順序佇列、鏈式佇列
阿新 • • 發佈:2018-12-10
Java實現佇列——順序佇列、鏈式佇列
概念
先進者先出,這就是典型的“佇列”。(First In, First Out,FIFO)。
我們知道,棧只支援兩個基本操作:入棧push()和出棧pop()。佇列跟棧非常相似,支援的操作也很有限,最基本的操作也是兩個:入隊和出隊。入隊 enqueue()
,讓一個數據到佇列尾部;出隊 dequeue()
,從佇列頭部取一個元素。
所以,佇列跟棧一樣,也是一種操作受限的線性表資料結構。
跟棧類似,用陣列實現的佇列叫做順序佇列,用連結串列實現的佇列叫做鏈式佇列。下面我們看下如何用Java程式碼如何實現。
順序佇列
程式碼如下:
public class QueueBasedArray implements QueueInterface { private String[] values;// 陣列 private int capacity = 0;// 陣列容量 private int head = 0;// 頭部下標 private int tail = 0;// 尾部下標 public QueueBasedArray(int capacity) { values = new String[capacity]; this.capacity = capacity; } @Override public Boolean enqueue(String value) { // tail == capacity 表示佇列末尾沒有空間了 if (tail == capacity) { // tail == capacity && head == 0 表示整個佇列都佔滿了。 if (head == 0) { return false; } // 資料搬移 for (int i = head; i < tail; i++) { values[i - head] = values[i]; } // 搬移完成後更新 head 和 tail tail -= head; head = 0; } values[tail] = value; tail++; return true; } @Override public String dequeue() { // 如果 head == tail 表示佇列為空 if (0 == tail) { return null; } String result = values[head]; head++; return result; } @Override public String toString() { return "QueueBasedArray{" + "values=" + Arrays.toString(values) + ", capacity=" + capacity + ", head=" + head + ", tail=" + tail + '}'; } }
測試程式碼:
QueueBasedArray qba = new QueueBasedArray(10); System.out.println(qba); for (int i = 0; i < 10; i++) { qba.enqueue("" + i + i + i); } System.out.println(qba); for (int i = 0; i < 10; i++) { qba.dequeue(); System.out.println(qba); } for (int i = 11; i < 20; i++) { qba.enqueue("" + i + i + i); } System.out.println(qba);
輸出結果:符合預期
QueueBasedArray{values=[null, null, null, null, null, null, null, null, null, null], capacity=10, head=0, tail=0}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=0, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=1, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=2, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=3, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=4, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=5, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=6, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=7, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=8, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=9, tail=10}
QueueBasedArray{values=[000, 111, 222, 333, 444, 555, 666, 777, 888, 999], capacity=10, head=10, tail=10}
QueueBasedArray{values=[111111, 121212, 131313, 141414, 151515, 161616, 171717, 181818, 191919, 999], capacity=10, head=0, tail=9}
鏈式佇列
程式碼如下:
public class QueueBasedLinkedList implements QueueInterface {
private Node head;
private Node tail;
/**
* 入隊
*
* @param value
* @return
*/
@Override
public Boolean enqueue(String value) {
Node newNode = new Node(value, null);
// tail為null,表示佇列中沒有資料
if (null == tail) {
head = newNode;
tail = newNode;
} else {
tail.next = newNode;
tail = newNode;
}
return true;
}
/**
* 出隊
*
* @return
*/
@Override
public String dequeue() {
// head == null,表示佇列為空。
if (null == head) {
return null;
}
// 獲取資料
String value = head.getItem();
// 移除頭結點,讓head指向下一個結點。
head = head.next;
// 如果此時的頭結點指向null,說明佇列已空,需要將tail指向null.
if (null == head) {
tail = null;
}
return value;
}
@Override
public String toString() {
return "QueueBasedLinkedList{" +
"head=" + head +
", tail=" + tail +
'}';
}
private static class Node {
String item;
private Node next;
public Node(String item, Node next) {
this.item = item;
this.next = next;
}
public String getItem() {
return item;
}
@Override
public String toString() {
return "Node{" +
"item='" + item + '\'' +
", next=" + next +
'}';
}
}
}
測試程式碼:
// 空佇列
QueueBasedLinkedList qbll = new QueueBasedLinkedList();
System.out.println("空佇列 " + qbll);
System.out.println();
// 入隊一個數據
System.out.println("資料入隊是否成功:" + qbll.enqueue("0000"));
System.out.println("入隊一個數據後:" + qbll);
System.out.println();
// 出隊一個數據
System.out.println("出隊的資料是:" + qbll.dequeue());
System.out.println("出隊一個數據後:" + qbll);
System.out.println();
// 異常測試:從空佇列中出隊,看結果
System.out.println("出隊的資料是1:" + qbll.dequeue());
System.out.println("出隊一個數據後1:" + qbll);
System.out.println();
// 入隊十條資料
for (int i = 0; i < 10; i++) {
System.out.println("資料入隊是否成功:" + qbll.enqueue("" + i + i + i));
System.out.println(qbll);
}
輸出結果:符合預期
空佇列 QueueBasedLinkedList{head=null, tail=null}
資料入隊是否成功:true
入隊一個數據後:QueueBasedLinkedList{head=Node{item='0000', next=null}, tail=Node{item='0000', next=null}}
出隊的資料是:0000
出隊一個數據後:QueueBasedLinkedList{head=null, tail=null}
出隊的資料是1:null
出隊一個數據後1:QueueBasedLinkedList{head=null, tail=null}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=null}, tail=Node{item='000', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=null}}, tail=Node{item='111', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=null}}}, tail=Node{item='222', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=null}}}}, tail=Node{item='333', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=Node{item='444', next=null}}}}}, tail=Node{item='444', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=Node{item='444', next=Node{item='555', next=null}}}}}}, tail=Node{item='555', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=Node{item='444', next=Node{item='555', next=Node{item='666', next=null}}}}}}}, tail=Node{item='666', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=Node{item='444', next=Node{item='555', next=Node{item='666', next=Node{item='777', next=null}}}}}}}}, tail=Node{item='777', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=Node{item='444', next=Node{item='555', next=Node{item='666', next=Node{item='777', next=Node{item='888', next=null}}}}}}}}}, tail=Node{item='888', next=null}}
資料入隊是否成功:true
QueueBasedLinkedList{head=Node{item='000', next=Node{item='111', next=Node{item='222', next=Node{item='333', next=Node{item='444', next=Node{item='555', next=Node{item='666', next=Node{item='777', next=Node{item='888', next=Node{item='999', next=null}}}}}}}}}}, tail=Node{item='999', next=null}}
完整程式碼請檢視
專案中搜索SingleLinkedList即可。
github傳送門 https://github.com/tinyvampirepudge/DataStructureDemo