常用資料結構之一佇列
佇列是一種特殊的
線性表,特殊之處在於它只允許在表的前端(front)進行刪除操作,而在表的後端(rear)進行插入操作,和棧一樣,佇列是一種操作受限制的線性表。進行插入操作的端稱為隊尾,進行刪除操作的端稱為隊頭。佇列中沒有元素時,稱為空佇列。
佇列的資料元素又稱為佇列元素。在佇列中插入乙個佇列元素稱為入隊,從佇列中刪除乙個佇列元素成為出隊。因為佇列只允許在一段插入,在另一端刪除,所以只有最早進入佇列的元素才能最先從佇列中刪除,故佇列又稱為先進先出(fifo—first in first out)
線性表。
[1]
建立順序佇列結構必須為其靜態分配或動態申請一片連續的儲存空間,並設定兩個指標進行管理。乙個是隊頭指標front,它指向隊頭元素;另乙個是隊尾指標rear,它指向下乙個入隊元素的儲存位置,如圖所示
每次在隊尾插入乙個元素是,rear增1;每次哎隊頭刪除乙個元素時,front增1。隨著插入和刪除操作的進行,佇列元素的個數不斷變化,佇列所佔的儲存空間也在為佇列結構所分配的連續空間中移動。當front=rear時,佇列中沒有任何元素,稱為空佇列。當rear增加到指向分配的連續空間之外時,佇列無法再插入新元素,但這時往往還有大量可用空間未被占用,這些空間是已經出隊的佇列元素曾經占用過得儲存單元。
順序佇列中的溢位現象:
(1) "下溢"現象:當隊列為空時,做出隊運算產生的溢位現象。「下溢」是正常現象,常用作程式控制轉移的條件。
(2)"真上溢"現象:當佇列滿時,做進棧運算產生空間溢位的現象。「真上溢」是一種出錯狀態,應設法避免。
(3)"假上溢"現象:由於入隊和出隊操作中,頭尾指標只增加不減小,致使被刪元素的空間永遠無法重新利用。當佇列中實際的元素個數遠遠小於向量空間的規模時,也可能由於尾指標已超越向量空間的上界而不能做入隊操作。該現象稱為"假上溢"現象。
在實際使用佇列時,為了使佇列空間能重複使用,往往對佇列的使用方法稍加改進:無論插入或刪除,一旦rear指標增1或front指標增1 時超出了所分配的佇列空間,就讓它指向這片連續空間的起始位置。自己真從maxsize-1增1變到0,可用取餘運算rear%maxsize和front%maxsize來實現。這實際上是把佇列空間想象成乙個環形空間,環形空間中的儲存單元迴圈使用,用這種方法管理的佇列也就稱為迴圈佇列。處了一些簡單應用之外,真正實用的佇列時迴圈佇列。
[2]在迴圈佇列中,當隊列為空時,有front=rear,而當所有佇列空間全佔滿時,也有front=rear。為了區別這兩種情況,規定迴圈佇列最多只能有maxsize-1個佇列元素,當迴圈佇列中只剩下乙個空儲存單元時,佇列就已經滿了。因此,佇列判空的條件時front=rear,而佇列判滿的條件時front=(rear+1)%maxsize。隊空和隊滿的情況如圖:
佇列可以用陣列q[1…m]來儲存,陣列的上界m即是佇列所容許的最大容量。在佇列的運算中需設兩個
指標:head,隊頭指標,指向實際隊頭元素;tail,隊尾指標,指向實際隊尾元素的下乙個位置。一般情況下,兩個
指標的初值設為0,這時隊列為空,沒有元素。陣列定義q[1…10]。q(i) i=3,4,5,6,7,8。頭
指標head=2,尾指標tail=8。佇列中擁有的元素個數為:l=tail-head。現要讓排頭的元素出隊,則需將頭指標加1。即head=head+1這時頭指標向上移動乙個位置,指向q(3),表示q(3)已出隊。如果想讓乙個新元素入隊,則需尾
指標向上移動乙個位置。即tail=tail+1這時q(9)入隊。當隊尾已經處理在最上面時,即tail=10,如果還要執行入隊操作,則要發生"上溢",但實際上佇列中還有三個空位置,所以這種溢位稱為"
假溢位"。
克服假溢位的方法有兩種。一種是將佇列中的所有元素均向低位址區移動,顯然這種方法是很浪費時間的;另一種方法是將
陣列儲存區看成是乙個首尾相接的環形區域。當存放到n位址後,下乙個位址就"翻轉"為1。在結構上採用這種技巧來儲存的佇列稱為
迴圈佇列。
佇列和棧一樣只允許在斷點處插入和刪除元素。
迴圈隊的入隊演算法如下:
1、tail=tail+1;
2、若tail=n+1,則tail=1;
3、若head=tail,即尾
指標與頭指標重合了,表示元素已裝滿佇列,則作上溢位錯處理;
4、否則,q(tail)=x,結束(x為新入出元素)。
佇列和棧一樣,有著非常廣泛的應用。
注意:(1)有時候佇列中還會設定表頭結點,就是在隊頭的前面還有乙個結點,這個結點的資料域為空,但是
指標域指向隊頭元素。
(2)另外,上面的計算還可以利用下面給出的公式cq.rear=(cq.front+1)/max;
當有表頭結點時,公式變為cq.rear=(cq.front+1)/(max+1)。
在佇列的形成過程中,可以利用線性鍊錶的原理,來生成乙個佇列。
基於鍊錶的佇列,要動態建立和刪除節點,效率較低,但是可以動態增長。
佇列採用的fifo(first in first out),新元素(等待進入佇列的元素)總是被插入到
鍊錶的尾部,而讀取的時候總是從鍊錶的頭部開始讀取。每次讀取乙個元素,釋放乙個元素。所謂的動態建立,動態釋放。因而也不存在溢位等問題。由於
鍊錶由結構體間接而成,遍歷也方便。
(1)初始化佇列:init_queue(q) ,初始條件:隊q 不存在。操作結果:構造了乙個空隊;
(2)入隊操作: in_queue(q,x),初始條件: 隊q 存在。操作結果: 對已存在的佇列q,插入乙個元素x 到隊尾,隊發生變化;
(3)出隊操作: out_queue(q,x),初始條件: 隊q 存在且非空,操作結果: 刪除隊首元素,並返回其值,隊發生變化;
(4)讀隊頭元素:front_queue(q,x),初始條件: 隊q 存在且非空,操作結果: 讀隊頭元素,並返回其值,隊不變;
(5)判隊空操作:empty_queue(q),初始條件: 隊q 存在,操作結果: 若q 為空隊則返回為1,否則返回為0。
[3]操作
型別
作用
返回值
例子
length(s)
函式
求字串s的長度
整型
s:='123456789';
l:=length(s);
copy(s,w,k)
函式
複製s中從w開始的k位
字串
s:='123456789';
s1:=copy(s,3,5);
val(s,k,code)
過程
將字串s轉為數值,存在k中;code是錯誤**
var s:string;k,code:integer;
begin
s:='1234';
val(s,k,code);
write(k);
str(i,s)
過程
將數值i轉為字串s
i:=1234;
str(i,s);
write(s);
delete(s,w,k)
過程
在s中刪除從第w位開始的k個字元
s := 'honest abe lincoln';
delete(s,8,4);
writeln(s);
insert(s1, s, w)
過程
將s1插到s中第w位
s := 'honest lincoln';
insert('abe ', s, 8);
pos(c, s)
函式
求字元c在s中的位置
整型
s := ' 123.5';
i :=pos(' ', s);
+
運算子
將兩個字串連線起來
s1:='1234';
s2:='5678';
s:=s1+s2;
在stl中,對佇列的使用很是較完美
下面給出迴圈佇列的運算演算法:
(1)將迴圈佇列置為空
//將佇列初始化
sequeue::sequeue()
(2)判斷迴圈佇列是否為空
int sequeue::empty()
(3)在迴圈佇列中插入新的元素x
void sequeue::addq(elemtype x)
} (4)刪除佇列中隊首元素
elemtype sequeue::delq()
} (5)取佇列中的隊首元素
elemtype sequeue::front()
學習資料結構(一) 佇列(2)
留下筆記。mycircularqueue k 構造器,設定佇列長度為 k front 從隊首獲取元素。如果隊列為空,返回 1 rear 獲取隊尾元素。如果隊列為空,返回 1 enqueue value 向迴圈佇列插入乙個元素。如果成功插入則返回真。dequeue 從迴圈佇列中刪除乙個元素。如果成功刪...
資料結構與演算法(一) 佇列
佇列是一種特殊的線性表。佇列元素的進出遵循 先進先出 原則 即只允許在前端 front 也就是隊頭進行刪除操作,而只能在後端 rear 也就是隊尾進行插入操作。如圖所示 author huang date 2020 06 11 16 28 description 用陣列模擬佇列 public cla...
資料結構學習一佇列整理
class myqueue 入隊成功了,返回true public boolean enqueue int x 出隊,成功返回true public boolean dequeue p start return true 獲取隊首元素 public intfront c判斷佇列是否為空 public...