之前總結過棧相關的知識,佇列可以模擬棧來看。棧只能在一端進行操作(棧頂),新增元素或者刪除等都只能在棧頂;而佇列有兩端可以操作,在一端新增元素,在另一端刪除元素。
我們把新增元素的一端稱為隊尾;刪除元素的一端稱為隊首。
比如生活中的排隊:城市中基本**都有,這就是乙個佇列。在隊伍最前面就是隊首,也是最先完成離開隊伍的。新來的只能在隊尾加入。
佇列的特點:用鍊錶、陣列都比較容易實現佇列。
鍊錶實現:比較簡單,在鍊錶首部刪除,鍊錶尾部插入即可。
鍊錶沒有長度限制,不會造成溢位,而且插入刪除也很簡單,是很適合的實現方式。
陣列實現:普通陣列方式,有著明顯的缺陷,長度固定、出隊時剩下所有元素都要向前挪動一位,這種出隊方式時間複雜度就是o(n)了。在此基礎上進行一些處理,形成乙個環,成為乙個迴圈佇列。
所以下面主要介紹的就是兩種佇列實現,用鍊錶實現的佇列 和 用陣列實現的迴圈佇列。
佇列主要兩個操作,入隊和出隊。
入隊(enqueue):即在隊尾插入新元素。
出隊(dequeue):即在隊首刪除乙個元素。
如果自己實現,可以新增更多公共操作,如隊長、是否隊空或隊滿、查詢等等。
下面實現中,為了更直觀的顯示出隊、入隊操作,都新增了乙個displayqueue()的方法。
單鏈表佇列實現很簡單,鍊錶首部即隊首,鍊錶尾部即隊尾,定義兩個引用分別指向隊首和隊尾,出隊、入隊直接刪除和插入即可。時間複雜度為o(1)。
優勢,沒有額外的操作,沒有長度的限制 不需擔心溢位。
示意圖大致如下:
具體**如下(可結合注釋,應該比較清晰):
public class queuelinkedlist
queuelinkedlist.displayqueue();
queuelinkedlist.dequeue();
queuelinkedlist.displayqueue();
queuelinkedlist.dequeue();
queuelinkedlist.displayqueue(); }
//定義隊首引用,指向鍊錶首部
private queuenodefront;
//定義隊尾引用,指向鍊錶尾部
private queuenoderear;
//節點定義
static class queuenode }
//初始化,空的佇列。
public queuelinkedlist()
//入隊,鍊錶尾部插入
public void enqueue(e value)
this.rear.next = newnode;
this.rear = newnode; }
//出隊,鍊錶首部刪除
public e dequeue()
//列印佇列所有元素,以及隊首、隊尾資訊
public void displayqueue()
system.out.println("front:" + this.front.data +"
queuenodetmpnode = this.front;
while (tmpnode != null)
system.out.println();
system.out.println();
}}
實驗結果為:
front:null
this is an empty queue!
front:1
1front:2
2front:3
3
若用普通陣列實現佇列,就會發現每次刪除隊首時所有元素都需要向前移動一位,這樣實現肯定是不合適的。
於是,在上述基礎上做一些處理,便形成了迴圈佇列:將陣列佇列看出乙個首尾相連的環形。用front和rear表示隊首和隊尾相關元素的下標(不一定是front是隊首下標,rear是隊尾下表),這樣就能很容易確定佇列的元素是哪些了。出隊、入隊改變這兩個值即可而不需要移動陣列中元素了。
下面實現用變數front和rear標識隊首、隊尾的下標,入隊和出隊的方式基本一致:陣列大小為capacity,即front=(font+1)%capacity 或 rear=(rear+1)%capacity。
也可以用front標識隊首,rear標識隊尾的下乙個位置,只是不同的標識含義, 初始化 和 隊列為空 及 隊列為滿 的判斷和處理需要注意,是不同的。(rear標識隊尾下乙個位置時,初始化front=rear=0,空即front==rear。而rear標識隊尾即下面的實現,可以具體看下)
大致示意圖如下(front和rear標識隊首、隊尾的下標):
實現**(可結合注釋檢視):
注:實現中的判空與判滿 使用了另乙個變數queuecount表示佇列元素個數,便於返回佇列大小。也可以使用front和rear之間關係進行判斷
public class queuecirclearray
queuecirclearray.displayqueue();
queuecirclearray.dequeue();
queuecirclearray.dequeue();
queuecirclearray.displayqueue();
queuecirclearray.enqueue(integer.valueof(10));
queuecirclearray.enqueue(integer.valueof(20));
queuecirclearray.displayqueue(); }
//陣列及大小
private object array;
private int capacity;
//隊首 隊尾對應陣列中的下標
private int front, rear;
//佇列的大小
private int queuecount;
public queuecirclearray()
public queuecirclearray(int capacity)
public boolean isfull()
public boolean isempty()
public void enqueue(object value)
public object dequeue()
public void displayqueue()
int tmp = this.front;
system.out.println("front:["+ this.front + "]" + this.array[this.front]
+"while(tmp != this.rear)
if (tmp == this.rear)
system.out.println(this.array[tmp]);
system.out.println();
}}
實驗結果:
front:null
this is an empty queue!
front:[0]1
1front:[2]3
3front:[2]3
3
資料結構之佇列(Queue)
佇列,顧名思義,也就是一條隊伍,進入隊伍的時候,只能從隊尾排隊,離開隊伍的時候,只能從隊首離開。佇列也有陣列實現和鏈式實現。用一般陣列實現佇列的時候,入隊,則在隊尾插入乙個元素,出隊,則將隊首的元素出隊。那麼,由於陣列的長度是固定的,入隊只能從隊尾入隊,因此經常性的出隊會使得隊首越來越靠近隊尾,隊首...
python資料結構之佇列(queue)
佇列是一種特殊的線性表,先進先出,只允許在前端進行刪除,在後端進行插入操作,它的操作方式與堆疊類似,區別在於佇列只允許在後端插入資料。在python中有相應的類 import queue q queue.queue for i in range 4 q.put i 將乙個值放入佇列中 while n...
C 資料結構之Queue(佇列)
queue,佇列,和我們日常生活中的佇列是同樣的規則,先進先出 從尾入,從首出。有外加的一些操作如 full 佇列是否已滿 serve and retrieve 檢視隊首元素同時去除 等等。在eclipse執行通過 h標頭檔案 queue.h created on 2015年8月22日 author...