由於插入和刪除分別在隊尾和隊頭進行,最先入隊的總是最先出隊。因此佇列的特點是「先進先出」。佇列的基本操作有建立佇列、判斷佇列是否為空、入隊和出隊。佇列和棧一樣,不支援對指定位置的插入和刪除。
宣告佇列介面queue< t >如下
package queue;
public
inte***ce
queue
實現queue< t >佇列介面的類有順序迴圈佇列、鏈式迴圈佇列和優先佇列。
佇列也有順序和鏈式兩種儲存結構,分別稱為順序佇列和鏈式佇列。
1.順序佇列
(1)使用順序表,出隊效率低
如果使用乙個順序表作為佇列的成員變數,入隊操作執行順序表尾插入,時間複雜度為0(1);出隊操作執行順序表頭刪除,時間複雜度都為o(n),效率較低。希望出隊操作效率也是o(1),因此,不使用乙個順序表作為佇列的成員變數。
(2)使用陣列,存在假溢位
順序佇列使用陣列儲存資料元素,用front、rear記住佇列頭、尾元素下標,入隊、出隊時,改變front、rear取值,則不需要移動元素。我們舉個例子來分析一下:
假設陣列長度為5.
(a)佇列初始空狀態,令front和rear都為-1;
(b)10入隊,此時front=rear=0;
(c)20和30入隊,此時front=0,rear=2;
(d)10和20出隊,此時front=rear=2;
(e)40和50入隊,front=2,rear=4;
(f)60想要入隊,front=2,rear=length=5,隊尾下標越界,假溢位。
思路可描述如下:
(1)當佇列空時,設定隊頭、隊尾下標front和rear=-1.
(2)當第乙個元素入隊,front=rear=0,同時改變了兩個下標。
(3)入隊操作,元素存入rear位置,rear++。
(4)出隊操作,返回front隊頭元素,front++。
(5)當入隊的元素個數超過陣列容量,rear下標越界,資料溢位,此時,由於之前已有若干元素出隊,陣列前部已多出許多儲存單元,所以這種溢位不是因為儲存空間不夠,稱為假溢位。
順序佇列存在兩個缺點:假溢位以及一次入隊/出隊操作需要同時改變兩個下標。為解決這個問題,我們可以把順序佇列設計成迴圈結構。
2.順序迴圈佇列
順序迴圈佇列就是邏輯上首尾相連的迴圈結構,這樣可以連續使用儲存單元。
設front是隊頭元素下標,rear是下乙個入隊元素下標。
(1)設定初始空隊列為font=rear=0,約定佇列空的條件就是front=rear。
(2)入隊操作改變rear,出隊操作改變front,變化規律如下,其中length表示陣列容量。
設length=5:
(a)初始化空佇列,令front=rear=0;
(b)10和20入隊。front=0,rear=2;
(c)10和20出隊。front=rear=2;
(d)30、40、50、60入隊。此時front=2,rear=1,佇列滿front==(rear+1)%length
(e)擴充容量後,front=0,rear=4.
(3)約定佇列滿條件是front==(rear+1)%length,此時佇列中依然有乙個空的位置,因為如果不保留乙個位置,佇列滿的條件也是front==rear,與佇列空條件相同。
(4)當佇列滿時再入隊,將陣列容量擴充一倍,按照佇列元素次序複製陣列元素。
3.順序迴圈佇列類
宣告順序迴圈佇列類seqqueue< t >如下,實現佇列介面。
package queue;
public
class
seqqueue
implements
queue
this
.element=
newobject
[length]
;this
.front=
this
.rear=0;
//設定空佇列
}public
seqqueue()
@override
public
boolean
isempty()
@override
public
boolean
add(t x)if(
this
.front==
(this
.rear+1)
%this
.element.length)
this
.front=0;
this
.rear=j;
}this
.element[
this
.rear]
=x;this
.rear=
(this
.rear+1)
%this
.element.length;
return
true;}
@override
public t peek()
@override
public t pool()
t temp=
(t)this
.element[
this
.front]
;this
.front=
(this
.front+1)
%this
.element.length;
return temp;
}}
(1)使用單鏈表,入隊效率低
1.使用乙個單鏈表作為佇列的成員變數,入隊操作執行單鏈表尾插入,時間複雜度為o(n),效率較低;出隊操作執行單鏈表頭刪除,時間複雜度為o(1)。因此,不能用乙個單鏈表作為佇列的成員變數,因為入隊操作達不到o(1)。
2.使用乙個迴圈雙鏈表作為佇列的成員變數,入隊操作執行迴圈雙鏈表尾插入,出隊操作執行迴圈雙鏈表頭刪除,時間複雜度都為o(1),但占用較多的空間。
(2)單鏈表設計,增加尾指標
以下為單鏈表(不帶頭結點)實現鏈式佇列的過程。設front和rear分別指向隊頭和隊尾結點,增加乙個尾指標,即可使入隊和出隊操作的空間複雜度都是o(1).
1.設定初始空佇列,front=rear=null,佇列空條件是front == null&&rear==null。
2.入隊操作,將x結點鏈在rear之後,並使rear指向x結點成為新的隊尾。
3.出隊操作,當佇列不空時,取得隊頭結點元素,刪除隊頭結點,並使front指向後繼結點。
4.當第乙個元素入隊或最後乙個元素出隊時,同時改變front和rear。
宣告鏈式佇列類linkedqueue如下,實現佇列介面,其中成員變數front和rear分別指向佇列頭結點和尾節點,資料型別都是單鏈表結點類node。
package queue;
import datastructure.node;
public
final
class
linkedqueue
implements
queue
@override
public
boolean
isempty()
@override
public
boolean
add(t x)
node
q=new
node
(x,null);if
(this
.front==null)
else
this
.rear=q;
return
true;}
@override
public t peek()
@override
public t pool()
t x=
this
.front.data;
//取得隊頭元素
this
.front=
this
.front.next;
//刪除隊頭結點if(
this
.front==null)
return x;
}}
結點node類:
package datastructure;
public
class
node
public
node()
public string tostring()
}
資料結構之佇列
八 佇列 鏈式佇列 鍊錶實現 隊尾 rear 隊首 front 靜態佇列 陣列實現 必須是迴圈佇列 需要幾個引數來確定,各引數含義 1 佇列初始化 front和rear值都是0 2 佇列非空 front代表佇列第乙個元素 rear代表佇列最後乙個元素的 下乙個元素 3 佇列空 front和rear相...
資料結構之佇列
與棧相反,佇列是一種先進先出的線性表,它只允許在表的一端進行,而在另一端刪除元 素。在佇列中,允許插入的一端叫做隊尾,允許刪除的一端則稱為隊頭。1 鏈佇列 佇列的鏈式表示和實現 用鍊錶表示的佇列簡稱為鏈佇列,乙個鏈佇列顯然需要兩個分別指示對頭和隊尾的指標 分別稱為頭指 針和尾指標 才能唯一確定。這裡...
資料結構之佇列
一 佇列的介紹 佇列 queue 是一種線性儲存結構。它有以下幾個特點 1 佇列中資料是按照 先進先出 fifo,first in first out 方式進出佇列的。2 佇列只允許在 隊首 進行刪除操作,而在 隊尾 進行插入操作。佇列通常包括的兩種操作 入佇列 和 出佇列。1.佇列的示意圖 佇列中...