【数据结构】--队列之循环队列
隊列:
- 一種訪問受限的線性表,只能在一端進行插入,另一端刪除
- 先進先出(FIFO),隊尾插入,隊頭刪除
隊列的分類:順序隊列、鏈表隊列
順序隊列:底層的數據結構是內存連續的,基于數組實現隊列的先進先出
隊頭為0,隊尾為4的刪除數據的時間復雜度為o(n),太高,因此我們一般不用,為了減低時間復雜度,我們一般使用循環隊列來處理順序隊列,也就是在邏輯上將數組變成一個環。
循環隊列:以數組的形式模擬出環狀結構,front是隊頭指針,隊頭(第一個)元素的下標;rear是隊尾指針,最后一個元素的下一個下標
注意:因為是環形設計,所以往后走不能直接++,容易越界,應該為front=(front+1)%size,rear=(rear+1)%size
插入的操作:頭指針front和尾指針rear開始同時指向0下標,每插入一個元素,rear向后移動一個下標;arr[rear]=xx;沒有循環,時 ? ? ? ? ? ? ? ? ? ? ? 間復雜度為o(1);
? ? ? ? ? ? ? ? ? ? ?? 注意:當rear指向最后一個5下標時,因為不能從5直接指向0,所以不能使用rear++,必須使用 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rear=(rear+1)%MAX_SIZE;eg: rear=(rear+1)%6;rear=(5+1)%6=0(rear是數組的下標);%為取余
刪除的操作:每刪除一個數據,front向后移動一個下標;front++;只刪除元素,不移動數據;時間復雜度為o(1);
判空和判滿:因為front==rear既可以判空也可以判滿,所以不能用此方法,這時,我們需要犧牲一個內存單元,每次滿的時候會 ? ? ? ? ? ? ? ? ? ? ? ? 選擇犧牲front之前的內存單元;(犧牲的內存單元不固定,每次輪番犧牲)
? ? ? ? ? ? ? ? ? ?? 判空empty:rear==front
? ? ? ? ? ? ? ? ? ?? 判滿full:(rear+1)%6==front
代碼實現:
結構設計:
typedefn int ElemType; #define MAX_SIZE 9;typedef struct Queue {ElemType arr[MAX_SIZE];//數組arr[10]int front;//隊頭指針int rear;//隊尾指針 }Queue,pQueue;初始化:
void init(pQueue pqu) {if(pqu!=NULL){pqu->frpnt=pqu->rear=0;} }入隊:
(1)判滿
int full(pQueue pue)//1 full,0 not full {return (pqu->rear+1)%MAX_SIZE==pqu->front ?1:0; }(2)
int enqueue(pQueue pqu,ElemType val)//1 success,0 fail {if(full(que)){return 0;}pqu->arr[pqu->rear]=val;pqu->rear=(pqu->rear+1)%MAX_SIZE;return 1; }出隊:
(1)判空
int empty(pQueue pue)//1 empty,0 not empty {return pqu->rear==pqu->front ? 1:0; }(2)
int dequeue(pQueue pue)//單純的刪除元素,沒有存儲 {if(empty(pue)){return 0;}pqu->front=(pqu->front+1)%MAX_SIZE;//向前走一個return 1; }獲取隊頭元素:
int front(pQueue pqu) {if(empty(pqu)){throw std::exception("queue is empty!");//一般使用c++處理機制,拋出異常//return -1;//-1有兩種情況,數值為-1或者隊列為空,因此是異常的,一般不建議這樣使用}return pqu->arr[pqu->front]; }?獲取隊尾元素:
int back(pQueue pqu) {if(empty(pqu)){throw std::exception("queue is empty!");//#include<iostream>c++頭文件// return -1;//-1代表隊列為空}return pqu->arr[(pqu->rear+MAX_SIZE-1)%MAX_SIZE];//回退一個,通過rear獲取上一個元素為隊尾元素 }? 函數的實現:
int main() {Queue que;init(&que);for(int i=0;i<8;i++){enqueue(&que,i);}int rtfront=front(&que);int reback=back(&que);printf("front:%d\n",rtfront);printf("back:%d\n",rtback);dequeue(&que);enqueue(&que,100);rtfront=front(&que);reback=back(&que);return 0; }考題:
1、為什么設計成環形?
因為其他方法復雜度太高,而環形入隊出隊時間復雜度都為O(1),速度快
2、為什么要空一個格子?
判斷為空:front==rear
判斷為滿:設計時最后一個格子不使用,rear再往后走一步front這時就滿,浪費一個單元格
因為front==rear既可以判空也可以判滿,所以不能用此方法,這時,我們需要犧牲一個內存單元,每次滿的時候會選擇犧牲front之前的內存單元;(犧牲的內存單元不固定,每次輪番犧牲)
3、因為是環形設計,所以往后走不能直接++,容易越界,應該為front=(front+1)%size,rear=(rear+1)%size
總結
以上是生活随笔為你收集整理的【数据结构】--队列之循环队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华为服务器上安装vm系统,云服务器安装v
- 下一篇: 硬件测试的思考和改进:有道词典笔的高效测