**
佇列(queue)簡稱隊 ,它也是 一種操作受限的線性表,其限制為僅允許在表的一端進行插入操作,而在表的另一端進行刪除操作。
把進行插入的一端成為隊的隊尾(rear),把進行刪除的一端稱為隊頭或隊首(front)。
向佇列中插入新元素稱為進隊或入隊(enqueue),新元素進隊後就成為新的隊尾元素;從佇列中刪除元素稱為出隊或離隊(dequeue),元素出隊後 , 其直接後繼元素就成為隊首元素。
//佇列抽象資料型別的定義如下:
adt queue
//elemtype 是自定義型別識別符號
資料關係:
r =基本運算:
initqueue
(&q)
:初始化佇列,構造乙個空佇列q。
destroyqueue
(&q)
:銷毀佇列,釋放佇列q占用的儲存空間。
queueempty
(q):判斷佇列是否為空,若佇列q為空,則返回真;否則返回假。
enqueue
(&q,e)
:進佇列,將元素e進隊,作為隊尾元素。
dequeue
(&q,
&e):出佇列,將佇列q**隊乙個元素,並將其賦值給e。
}
佇列中資料元素的邏輯關係呈線性關係,所以佇列可以像線性表一樣採取順序儲存結構進行儲存,即分配一塊連續的儲存空間來存放佇列中的元素,並採用兩個整型變數來反映佇列中元素的變化,它們分別儲存隊首元素和隊尾元素的下標位置,分別稱為隊首指標(隊頭指標)和隊尾指標。採用順序儲存結構的隊列為順序隊(sequential queue)。假設佇列中元素個數最多不超過整數maxsize,所有的元素都具有elemtype資料型別,則順序隊型別sqqueue宣告如下:
//自定義資料型別
typedef
char elemtype;
typedef
struct queue
sqqueue;
在順序隊中隊頭指標front指向當前佇列中隊頭元素的前乙個位置,隊尾指標rear指向當前佇列中隊尾元素的位置。
(1)順序隊中實現佇列的基本運算
空列
a,b,d,c,e進隊
出隊兩次
出隊三次
綜上所述,對於q所指的順序隊,初始時設定q->front = q->rear = -1,可以歸納出對後面演算法設計來說非常重要的4個元素:
在順序隊上對應佇列的基本運算演算法設計如下:
1)初始化佇列initqueue(sqqueue *&q):
//構造乙個空佇列q,將front和rear指標均設定成初始狀態,即-1。
void
initqueue
(sqqueue *
&q)
2)銷毀佇列destroyqueue(sqqueue *&q):
//釋放佇列q占用的儲存空間。
void
destroyqueue
(sqqueue *
&q)
3)判斷佇列是否為空queueempty(sqqueue *q):
//若佇列q為空,返回值為真;否則返回假。
bool queueempty
(sqqueue *q)
4)進佇列enqueue(sqqueue *&q,elemtype e):
//首先判斷佇列q是否滿,若滿,則返回假,結束函式;
//若不滿,rear++,將元素e儲存在data的rear位置,返回值為真。
bool enqueue
(sqqueue *
&q,elemtype e)
else
}
5)出佇列dequeue(sqqueue *&q,elemtype &e):
//與上述的進佇列類似,首先判斷佇列是否為空,若為空,則返回假;
//若不空,front++,然後data的值賦給元素e,返回值為真。
bool dequeue
(sqqueue *
&q,elemtype &e)
else
}
存在問題:這樣的操作容易出現假滿的情況,即上面圖3、4,若出現假滿的情況,佇列q將無法繼續進隊,從而浪費空間,佔記憶體。
即存在問題:如何解決假滿問題,使之能持續迴圈使用?
(2)環形隊中實現佇列的基本運算
因為隊滿條件設定不合理導致隊滿條件成立而佇列中仍然有空位置的情況稱為假溢位(false overflow)。可以看出,在出現假溢位時隊尾指標rear指向data陣列的最大下標,而另一端仍存在若干空位置。解決的方法是把data陣列的前端和後端連線起來,形成乙個環形陣列,即把儲存佇列元素的陣列從邏輯上看成乙個環,稱為環佇列或者迴圈佇列(circular queue)。
環形佇列首尾相連後,當隊尾指標rear = maxsize-1後,再進入乙個位置就達到了0,於是就可以使用另一端的空位置存放佇列元素了。實際上儲存器中的位址總是連續編號的,為此採用數學上的求餘運算(%)來實現:
//隊頭指標front迴圈增1:front = (front + 1)% maxsize
//隊尾指標rear迴圈增1:rear = (rear + 1)% maxsize
環形佇列的隊頭指標front和隊尾指標rear初始化都設定為0,即front = rear =0。在進隊元素和出隊元素時,隊尾指標和隊頭指標分別迴圈加1.
那麼,迴圈佇列q的隊滿和隊空條件如何設定呢?顯然,隊空的條件是q->front==q-> rear,當隊滿的條件也是q->front ==q-> rear。
那,如何區分隊滿和隊空呢?改為以「隊尾指標迴圈增1時等於隊頭指標」作為隊滿條件,也就是嘗試僅對一次,若達到隊頭,就認為隊滿了,不能再進隊。這樣的話,佇列就少用乙個元素空間,即該佇列在任何時刻最多只能有maxsize-1個元素。
在這樣設計的環形佇列中,實現佇列的基本運算演算法如下:
1)初始化佇列initqueue(sqqueue *&q):
//構造乙個空佇列q,將front和rear指標均設定成初始狀態,即-1。
void
initqueue
(sqqueue *
&q)
2)銷毀佇列destroyqueue(sqqueue *&q):
//釋放佇列q占用的儲存空間。
void
destroyqueue
(sqqueue *
&q)
3)判斷佇列是否為空queueempty(sqqueue *q):
//若佇列q為空,返回值為真;否則返回假。
bool queueempty
(sqqueue *q)
4)進佇列enqueue(sqqueue *&q,elemtype e):
//首先判斷佇列q是否滿,若滿,則返回假,結束函式;
//若不滿,q->rear = (q->rear + 1) % maxsize,將元素e儲存在data的rear位置,返回值為真。
bool enqueue
(sqqueue *
&q,elemtype e)
else
}
5)出佇列dequeue(sqqueue *&q,elemtype &e):
//與上述的進佇列類似,首先判斷佇列是否為空,若為空,則返回假;
//若不空,q->front = (q->front + 1) % maxsize,然後data的值賦給元素e,返回值為真。
bool dequeue
(sqqueue *
&q,elemtype &e)
else
}
環形佇列解決了假滿現象,更加充分地利用了佇列空間。但並非所有情況下都採用環形佇列。因為在環形佇列中,隨著多次元素的進隊和出隊,出隊元素的空間有可能被新入隊的元素所覆蓋。在有些情況下,需要利用出隊的元素來求解,所以是否使用環形佇列視情況而定。 C語言學習筆記
include include void swap int p1,int p2 void swapa int arr,int n void printfa int arr,int n int main int argc,char argv swap i,j printfa array,6 swapa...
C語言學習筆記
file 結構 包含在stdio.h裡 ifndef file defined struct iobuf typedef struct iobuf file define file defined endif fread 功 能 從乙個流中讀資料 函式原型 size t fread void buf...
C語言學習筆記
我們學習c語言最開始入門的時候,都是先從c語言學習 c語言教材書籍開始學習,這些是我摘要的一些內容。第一章 c 語言概述 語言概述 1.1 物件導向程式設計基本概念 1.2 c 語言是一種物件導向的程式設計 語言 1.3 c 程式結構的特點 程式結構的特點 1.4 visual c 6.0簡介 簡介...