理論參考其他文章!!!
我們假設乙個佇列有n個元素,則順序儲存的佇列需建立乙個大於n的陣列,並把佇列的所有元素儲存在陣列的前n個單元,陣列下標為0的一端即是隊頭。所謂的入佇列操作,其實就是在隊尾追加乙個元素,不需要移動任何元素,因此時間複雜度為0(1)。
與棧不同的是,佇列元素的出列是在隊頭,即下標為0的位置,那也就意味著,佇列中的所有元素都得向前移動,以保證佇列的隊頭(也就是下標為0的位置)不為空,此時的時間複雜度為0(n)。
可有時想想,為什麼出佇列時一定要全部移動呢,如果不去限制佇列的元素必須儲存在陣列的前n個單元這一條件,出隊的效能就會大大增加。也就是說,隊頭不需要一定在下標為0的位置,比如也可以是a[1]等。
為了避免當只有乙個元素時,隊頭和隊尾重合使處理變得麻煩,所以引入兩個指標,front指標指向隊頭元素,rear指標指向隊尾元素的下乙個位置,這樣當front等於rear時,此佇列不是還剩乙個元素,而是空佇列。
假設是長度為5的陣列,初始狀態,空佇列如所示,front與 rear指標均指向下標為0的位置。然後入隊a1、a2、a3、a4, front指標依然指向下標為0位置,而rear指標指向下標為4的位置。
出隊a1、a2,則front指標指向下標為2的位置,rear不變,如下圖所示,再入隊a5,此時front指標不變,rear指標移動到陣列之外。嗯?陣列之外,那將是**?
問題還不止於此。假設這個佇列的總個數不超過5個,但目前如果接著入隊的話,因陣列末尾元素已經占用,再向後加,就會產生陣列越界的錯誤,可實際上,我們的佇列在下標為0和1的地方還是空閒的。我們把這種現象叫做「假溢位」。
為了解決這個問題,我們後面會引入迴圈佇列的概念。
前面講到了佇列的「假溢位」,解決假溢位的辦法就是後面滿了,就再從頭開始,也就是頭尾相接的迴圈。我們把佇列的這種頭尾相接的順序儲存結構稱為迴圈佇列。
比如昨天的例子,rear可以改為指向下標為0的位置,這樣就不會造成指標指向不明的問題了。
但是如果繼續進行入隊操作的話,比如繼續插入a6、a7,則rear指標就與front指標重合,同時指向下標為2的位置。
我們來討論第二種方法,由於rear可能比front大,也可能比front小,所以儘管它們只相差乙個位置時就是滿的情況,但也可能是相差整整一圈。所以若佇列的最大尺寸為queuesize,那麼佇列滿的條件是(rear+1) %queuesize == front (取模「%的目的就是為了整合rear與front大小為乙個問題)。
比如上面這個例子, queuesize = 5,當 front=0,而 rear=4, (4+1) %5 = 0,所以此時佇列滿。再比如,front = 2而rear =1。(1 + 1) %5 = 2,所以此時 佇列也是滿的。而對於下圖, front = 2而rear= 0, (0+1) %5 = 1,1!=2,所以此時佇列並沒有滿。
另外,當rear > front時,此時佇列的長度為rear—front。但當rear < front時,佇列長度分為兩段,一段是queuesize-front,另一段是0 + rear,加在一起,佇列長度為rear-front + queuesize,因此通用的計算佇列長度公式為:
(rear—front + queuesize) % queuesize
有了這些講解,現在實現迴圈佇列的**就不難了。具體的例子程式可以參照前面說的順序佇列。
package com.perkinl.queue;public inte***ce queue
package com.perkinl.queue;public class array
// 無引數的建構函式,預設陣列的容量capacity=10
public
array()
// 獲取陣列的容量
public int
getcapacity()
// 獲取陣列中的元素個數
public int
getsize()
// 返回陣列是否為空
public boolean
isempty()
// 在index索引的位置插入乙個新元素e
public void
add(int index,
e e)
// 向所有元素後新增乙個新元素
public void
addlast(e e)
// 在所有元素前新增乙個新元素
public void
addfirst(e e)
// 獲取index索引位置的元素
public
e get(int index)
public
e getlast()
public
e getfirst()
// 修改index索引位置的元素為e
public void
set(int index,
e e)
// 查詢陣列中是否有元素e
public boolean
contains(e e)
return false;
} // 查詢陣列中元素e所在的索引,如果不存在元素e,則返回-1
public int
find(e e)
return -1;}
// 從陣列中刪除index位置的元素, 返回刪除的元素
public
e remove(int index)
// 從陣列中刪除第乙個元素, 返回刪除的元素
public
e removefirst()
// 從陣列中刪除最後乙個元素, 返回刪除的元素
public
e removelast()
// 從陣列中刪除元素e
public void
removeelement(e e)
@override
public string tostring()
return res.tostring();
} // 將陣列空間的容量變成newcapacity大小
private void
resize(int newcapacity)
}
package com.perkinl.queue;/*** 迴圈佇列
*@param
<
e>
*/public class loopqueue implements queue
public
loopqueue()
public int
getcapacity()
@override
public boolean
isempty()
@override
public int
getsize()
@override
public void
enqueue(e e)
@override
public
e dequeue()
@override
public
e getfront()
private void
resize(int newcapacity)
@override
public string tostring()
return res.tostring();
} public static void
main(string args)}}
}
JAVA資料結構之迴圈佇列的實現
1 迴圈佇列circlequeue類的實現 如下所示 public class circlequeue 入隊 boolean ret array null capacity 0 if ret return ret 出隊 public object retrieve return data 獲取佇列中...
資料結構之迴圈佇列
資料結構之佇列 迴圈佇列 ide vs2010 佇列操作 初始化 入隊 插入隊尾 出隊 即取隊頭 判斷佇列是否非空 滿 include using namespace std define max len 100 定義節點型別 typedef struct queue queue 初始化 void ...
資料結構之迴圈佇列
4.10 佇列的定義 佇列定義 一種先進先出的線性表。允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。隊頭 隊尾 出佇列 a1 a2 a3 a4 an 入佇列 佇列有類似線性表的各種操作,不同的就是插入資料只能在隊尾進行,刪除資料只能在隊頭進行。線性表有線性儲存和鏈式儲存。棧是線性表,有這兩種儲存方...