【数据结构】队列-顺序队列、循环队列、链队、双端队列
定義
隊列是只允許在一端進行插入,而在另一端進行刪除的線性表。
隊頭(Front):允許刪除的一端,又稱為隊首。
隊尾(Rear): 允許插入的一端。
先進入隊列的元素必然先離開隊列,即先進先出(First In First Out)簡稱FIFO。
**對比:**棧中元素后進去的必然先出來,即后進先出LIFO(Last In First Out)。
順序隊列
用數組來實現隊列,可以將隊首放在數組下標為0的位置。
不要求從數組首位開始存儲隊列。也就是說隊首不一定要在數組下標為0的位置。那如何表示隊首呢?
#define MaxSize 50 //定義隊列中元素的最大個數 typedef struct{ ElemType data[MaxSize]; //存放隊列元素yichu int front,rear; //隊頭指針和隊尾指針 } SqQueue;隊列的順序實現是指分配一塊連續的存儲單元存放隊列中的元素,井附設兩個指針 front和 rear 分別指示隊頭元素和隊尾元素的位置。設隊頭指針指向隊頭元素,隊尾指針指向隊尾元素的下一個位置。
初始狀態(隊空條件): Q.front==Q.rear=0 。
進隊操作:隊不滿時,先送值到隊尾元素 , 再將隊尾指針加1
出隊操作:隊不空時,先取隊頭元素值,再將隊頭指針加1
當rear到達數組末端,會出現“假溢出”
循環隊列
將順序隊列臆造為一個環狀的空間,即把存儲隊列元素的表從邏輯上看成一個環 ,稱為循環隊列 。當隊首指針 Q.front=MaxSize-1 后,再前進一個位置就自動到 0,這可以利用除法取余運算(%)來實現 。
初始時: Q.front=Q.rear=O
隊首指針進 1: Q.front=(Q.front+1)%MaxSize
隊尾指針進 1: Q.rear=(Q.rear+l)%MaxSize
隊列長度:(Q.rear+MaxSize-Q.front)%MaxSize
那么,循環隊列隊全和隊滿的判斷條件是什么呢? 顯然,隊空的條件是 Q.front=Q.rear。如果入隊元素的速度快于出隊元素的速度 , 隊尾指針很快就趕上了隊首指針,如圖d1 所示,此時可以看出隊滿時也有 Q.front=Q.rear。 為了區分隊空還是隊滿的情況, 下面給出常用的一種處理方式:
犧牲一個單元來區分隊空和隊滿, 入隊時少用 一個隊列單元,這是一種較為普遍的做法 ,約定以 “隊頭指針在隊尾指針的下一位置作為隊滿的標志”,如圖(d2)所示:
隊滿條件為:(Q.rear+1)%MaxSize == Q.front
隊空條件仍為: Q.front ==Q.rear
隊列中元素的個數:(Q .rear-Q.front+MaxSize)% MaxSize
循環隊列的操作
1.初始化
void InitQueue(&Q){Q.rear=Q.front=0; //初始化隊首、隊尾指針 }2.判隊空
bool isEmpty(Q){if(Q.rear==Q.front) //隊空條件return true;elsereturn false; }3.入隊
bool EnQueue(SqQueue &Q,ElemType x) {if ((Q.rear+1)%MaxSize==Q.front) //隊滿return false; Q.data[Q.rear]=x;Q.rear=(Q.rear+1)%MaxSize;return true; //隊尾指針加 1 取模 }4.出隊
bool DeQueue(SqQueue &Q,ElemType &x) {if(Q.rear==Q.front) //隊空,報錯return false;x=Q.data[Q.front];Q.front=(Q.front+1)%MaxSize; //隊頭指針加 1 取模return true; }鏈式隊列
隊列的鏈式存儲結構,其實就是線性表的單鏈表,只不過需要加點限制,只能表尾插入元素,表頭刪除元素。
為了方便操作,我們分別設置隊頭指針和隊尾指針,隊頭指針指向頭結點,隊尾指針指向尾結點。
鏈式隊列的操作
1.入隊
我們知道隊列只能從隊尾插入元素,隊頭刪除元素。于是入隊就是在隊尾指針進行插入結點操作。鏈隊的插入操作和單鏈表的插入操作是一致的。
2.出隊
出隊就是頭結點的后繼結點出隊,然后將頭結點的后繼改為它后面的結點。
雙端隊列
參考資料
王道數據結構
總結
以上是生活随笔為你收集整理的【数据结构】队列-顺序队列、循环队列、链队、双端队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数据结构】栈-顺序栈、链式栈、共享栈
- 下一篇: Maximum Subsequence