資料結構之 佇列(Queue)的實現 Java
阿新 • • 發佈:2018-12-12
佇列 - 實現
為了實現佇列,我們可以使用動態陣列和指向佇列頭部的索引。
如上所述,佇列應支援兩種操作:入隊和出隊。入隊會向佇列追加一個新元素,而出隊會刪除第一個元素。 所以我們需要一個索引來指出起點。
這是一個供你參考的實現:
// "static void main" must be defined in a public class. class MyQueue { // store elements private List<Integer> data; // a pointer to indicate the start position private int p_start; public MyQueue() { data = new ArrayList<Integer>(); p_start = 0; } /** Insert an element into the queue. Return true if the operation is successful. */ public boolean enQueue(int x) { data.add(x); return true; }; /** Delete an element from the queue. Return true if the operation is successful. */ public boolean deQueue() { if (isEmpty() == true) { return false; } p_start++; return true; } /** Get the front item from the queue. */ public int Front() { return data.get(p_start); } /** Checks whether the queue is empty or not. */ public boolean isEmpty() { return p_start >= data.size(); } }; public class Main { public static void main(String[] args) { MyQueue q = new MyQueue(); q.enQueue(5); q.enQueue(3); if (q.isEmpty() == false) { System.out.println(q.Front()); } q.deQueue(); if (q.isEmpty() == false) { System.out.println(q.Front()); } q.deQueue(); if (q.isEmpty() == false) { System.out.println(q.Front()); } } }
缺點
上面的實現很簡單,但在某些情況下效率很低。 隨著起始指標的移動,浪費了越來越多的空間。 當我們有空間限制時,這將是難以接受的。
讓我們考慮一種情況,即我們只能分配一個最大長度為 5 的陣列。當我們只新增少於 5 個元素時,我們的解決方案很有效。 例如,如果我們只調用入隊函式四次後還想要將元素 10 入隊,那麼我們可以成功。
但是我們不能接受更多的入隊請求,這是合理的,因為現在佇列已經滿了。但是如果我們將一個元素出隊呢?
實際上,在這種情況下,我們應該能夠再接受一個元素。
迴圈佇列
此前,我們提供了一種簡單但低效的佇列實現。
更有效的方法是使用迴圈佇列。 具體來說,我們可以使用固定大小的陣列
兩個指標
來指示起始位置和結束位置。 目的是重用
我們之前提到的被浪費的儲存
。
設計迴圈佇列
設計你的迴圈佇列實現。 迴圈佇列是一種線性資料結構,其操作表現基於 FIFO(先進先出)原則並且隊尾被連線在隊首之後以形成一個迴圈。它也被稱為“環形緩衝器”。 迴圈佇列的一個好處是我們可以利用這個佇列之前用過的空間。在一個普通佇列裡,一旦一個佇列滿了,我們就不能插入下一個元素,即使在佇列前面仍有空間。但是使用迴圈佇列,我們能使用這些空間去儲存新的值。 你的實現應該支援如下操作:
- MyCircularQueue(k): 構造器,設定佇列長度為 k 。
- Front: 從隊首獲取元素。如果佇列為空,返回 -1 。
- Rear: 獲取隊尾元素。如果佇列為空,返回 -1 。
- enQueue(value): 向迴圈佇列插入一個元素。如果成功插入則返回真。
- deQueue(): 從迴圈佇列中刪除一個元素。如果成功刪除則返回真。
- isEmpty(): 檢查迴圈佇列是否為空。
- isFull(): 檢查迴圈佇列是否已滿。
示例:
MyCircularQueue circularQueue = new MycircularQueue(3); // 設定長度為3 circularQueue.enQueue(1); // 返回true circularQueue.enQueue(2); // 返回true circularQueue.enQueue(3); // 返回true circularQueue.enQueue(4); // 返回false,佇列已滿 circularQueue.Rear(); // 返回3 circularQueue.isFull(); // 返回true circularQueue.deQueue(); // 返回true circularQueue.enQueue(4); // 返回true circularQueue.Rear(); // 返回4
程式碼如下:
public class MyCircularQueue {
int [] mcq ;
int k;
int head=0;
int tail=0;
/** Initialize your data structure here. Set the size of the queue to be k. */
public MyCircularQueue(int k) {
this.k=k+1;
mcq=new int[k+1];
for(int i:mcq){
mcq[i]=-1;
}
head=0;
tail=0;
}
/** Insert an element into the circular queue. Return true if the operation is successful. */
public boolean enQueue(int value) {
if(isFull()){
return false;
}
else{
if(tail!=k-1){
mcq[tail++]=value;
}
else{
mcq[tail]=value;
tail=0;
}
return true;
}
}
/** Delete an element from the circular queue. Return true if the operation is successful. */
public boolean deQueue() {
if(isEmpty()){
return false;
}
else {
mcq[head]=0;
if(head!=k-1){
head++;
}
else {
head=0;
}
return true;
}
}
/** Get the front item from the queue. */
public int Front() {
if(isEmpty()){
return -1;
}
else {
return mcq[head];
}
}
/** Get the last item from the queue. */
public int Rear() {
if(isEmpty()){
return -1;
}
else {
if(tail!=0){
return mcq[tail-1];
}
else{
return mcq[k-1];
}
}
}
/** Checks whether the circular queue is empty or not. */
public boolean isEmpty() {
if(head==tail){
return true;
}
else {
return false;
}
}
/** Checks whether the circular queue is full or not. */
public boolean isFull() {
if((head==0 && tail==k-1) || head-1==tail){
return true;
}
else {
return false;
}
}
public static void main(String[] args) {
MyCircularQueue t=new MyCircularQueue(6);
System.out.println(t.enQueue(1));
System.out.println(t.enQueue(2));
System.out.println(t.enQueue(3));
System.out.println(t.enQueue(4));
System.out.println(t.enQueue(5));
System.out.println(t.enQueue(6));
System.out.println(t.Rear());
System.out.println(t.Rear());
System.out.println(t.deQueue());
System.out.println(t.enQueue(5));
System.out.println(t.Rear());
System.out.println(t.deQueue());
System.out.println(t.Front());
System.out.println(t.deQueue());
System.out.println(t.deQueue());
System.out.println(t.deQueue());
}
}