考研數(shù)據(jù)結(jié)構(gòu)筆記——3.隊列

隊列

隊列的基本概念

隊列是一種操作受限的線性表烙懦,只允許在表的一端進行插入驱入,而在表的另一端進行刪除;向隊列中插入元素稱為入隊或者進隊氯析,刪除元素稱為出隊或者離隊亏较;隊列的操作特性是先進先出

  • 隊頭:允許刪除的一端,又稱為隊首
  • 隊尾:允許插入的一段
  • 空隊列:不含任何元素的空表

隊列常見的基本操作

隊列常見的基本操作主要有構(gòu)造一個空隊列InitQueue(&Q)掩缓、判斷隊列為空QueueEmpty(Q)雪情、入隊EnQueue(&Q,x)、出隊DeQueue(&Q,&x)拾因、讀隊頭元素GetHead(Q,&x)

需要注意的是,隊列是操作受限的線性表旷余,因此不是所有對線性表的操作都可以作為隊列的操作绢记,比如,不可以隨便讀取隊列中間的某個數(shù)據(jù)

隊列的順序存儲結(jié)構(gòu)

隊列的順序?qū)崿F(xiàn)是指分配一塊連續(xù)的存儲單元存放隊列中的元素正卧,并設(shè)置兩個指針front和rear分別指向隊頭元素和隊尾元素的位置蠢熄;設(shè)隊頭指針指向隊頭元素,隊尾指針指向隊尾元素的下一個位置

#define MaxSize 50      //定義隊列中元素的最大個數(shù)
typedef struct{
    ElemType data[MaxSize];
    int front,rear;     //定義隊頭指針和隊尾指針
} SqQueue;

初始條件(隊空條件):Q.front = 0,Q.rear = 0(隊尾的下一個位置等于0炉旷,即隊尾位置等于-1签孔,隊列為空
進隊操作:隊列不滿時,先送值到隊尾元素窘行,再將隊尾指針加一
出隊操作:隊列不為空時饥追,先彈出隊頭元素值,再將隊頭指針加一

d注意:Q.rear == MaxSize并不能作為隊列已滿的條件罐盔,因為即使經(jīng)過多次的進隊但绕、出隊,即使隊尾指針Q.rear已經(jīng)達到了MaxSize的位置惶看,但是隊頭指針同樣可能變化捏顺,使隊頭發(fā)生后移,導致data數(shù)組中仍然存在可以存放元素的空位置纬黎,實際上是一種“假溢出”幅骄,這也是順序隊列的一種缺點。

循環(huán)隊列

前面說本今,順序隊列的缺點是對隊頭元素的刪除操作會導致data數(shù)組中仍然存在未被利用的隊頭空間拆座,甚至出現(xiàn)“假溢出現(xiàn)象”主巍,循環(huán)隊列解決了這種問題;將順序隊列臆造成為一個環(huán)狀的空間懂拾,即把存儲隊列的線性表從邏輯上視為一個環(huán)煤禽,稱為循環(huán)隊列。

在循環(huán)隊列中岖赋,當隊首指針為MaxSize-1時檬果,其下一個位置為0;循環(huán)隊列依靠除法的取余操作實現(xiàn)唐断。

  • 初始時:頭結(jié)點的位置指針Q.front=0选脊,指向尾結(jié)點下一個元素位置的指針Q.rear=0
  • 隊首指針進1:Q.front=(Q.front+1)%MaxSize
  • 隊尾指針進1:Q.rear=(Q.rear+1)%MaxSize
  • 隊列長度:(Q.rear+MaxSize-Q.front)%MaxSize (保證正數(shù)?脸甘?恳啥?)
  • 出隊入隊時,指針都向順時針方向加1

判斷循環(huán)隊列隊滿或者隊空時會發(fā)現(xiàn)丹诀,循環(huán)隊列隊空的條件為Q.front==Q.rear钝的,和普通隊列一致;但循環(huán)隊列隊滿時铆遭,由于Q.rear指向隊末元素的下一個位置硝桩,條件仍然是Q.front==Q.rear,因此為了區(qū)分隊空還是隊滿枚荣,有幾種處理方式碗脊;

1.犧牲一個單元來區(qū)分隊空和隊滿,入隊時少用一個隊列單元橄妆;約定以隊頭指針指向隊尾指針指向的下一個位置作為隊滿的標志衙伶;

  • 隊滿條件:(Q.rear+1)%MaxSize==Q.front
  • 隊空條件:Q.rear==Q.front
  • 隊列中元素的個數(shù)Q.rear-Q.front+MaxSize)%MaxSize(當Q.rear-Q.front為正數(shù)時,和Q.rear-Q.front等價害碾;當Q.rear越過0的位置矢劲,變成一個小于Q.front的值時,加上MaxSize使整個值非負慌随,便于取余數(shù))

2.類型中新增表示元素個數(shù)的數(shù)據(jù)成員Q.size卧须,無視Q.rear==Q.front這一判別條件;這樣循環(huán)隊列的判空條件為Q.size==0儒陨,隊滿的判定條件為Q.size==MaxSize-1花嘶;對于這兩種情況,都有Q.rear==Q.front

3.類型中增加Q.tag成員蹦漠,通過記錄導致Q.rear==Q.front的原因區(qū)分隊滿還是隊空椭员;若因刪除導致Q.rear==Q.front,則為隊空笛园,記錄為tag等于0隘击;若因插入導致Q.rear==Q.front侍芝,則為隊滿,記錄為tag等于1

循環(huán)隊列的操作

初始化

void InitQueue(SqQueue &Q){
    Q.rear = Q.front = 0;  //初始化隊首埋同、隊尾指針為0
}

判隊空

bool isEmpty(SqQueue Q){
    if (Q.rear == Q.front)  //隊空條件
        return true;
    else
        return false;
}

入隊

bool EnQueue(SqQueue &Q,ElemType x){
    if ((Q.rear + 1)%MaxSize == MaxSize)
        return false;
    Q.data[Q.rear] = x; //原指針指向的是下一個應(yīng)該填充的位置
    Q.rear = (Q.rear + 1)%MaxSize;  //為了防止進入下個周期而大于MaxSize
    return true州叠;
}

出隊

bool DeQueue(SqQueue &Q,ElemType x){
    if(Q.rear == Q.front)
        return true;
    x = Q.data[Q.front];
    Q.front = (Q.front + 1)%MaxSize;
    return true;
}

隊列的鏈式存儲結(jié)構(gòu)

隊列的鏈式表示稱為鏈隊列,它實際上是一個帶有頭指針和尾指針的單鏈表凶赁;頭指針指向隊頭結(jié)點咧栗,尾指針指向隊尾結(jié)點,即單鏈表的最后一個結(jié)點

注意:在隊列的順序存儲中虱肄,尾指針指向隊尾元素的下一個結(jié)點致板;而在隊列的鏈式存儲結(jié)構(gòu)中,尾指針指向的是隊尾元素所在的結(jié)點

隊列的鏈式存儲類型可以描述為

typedef struct{     //鏈式隊列的結(jié)點
    ElemData data;
    struct LinkNode *next;
}LinkNode;

typedef struct{     //鏈式隊列本身
    LinkNode *front,*next;  //隊列的隊頭和隊尾指針
}LinkQueue;

當隊列的隊頭指針Q.front == NULL和隊尾指針Q.next == NULL時咏窿,鏈式隊列為空

出隊時斟或,首先判斷隊是否為空听怕;如果不為空弄兜,則將其從鏈表中摘除,并且使Q.front指向下一個結(jié)點(若該結(jié)點為最后一個結(jié)點智听,則將Q.frontQ.next都設(shè)為NULL根欧;入隊時怜珍,建立一個新結(jié)點,將新結(jié)點插入鏈表的尾部咽块,并讓Q.rear指向這個新插入的結(jié)點(若原隊列為空绘面,則令Q.front也指向這個結(jié)點)

因此欺税,不帶頭節(jié)點的鏈式隊列由于存在為空的可能侈沪,因此操作上比較麻煩;因此通常將鏈式隊列設(shè)計成帶頭結(jié)點的單鏈表晚凿,這樣插入和刪除操作能得到統(tǒng)一

用單鏈表表示的鏈式隊列適合數(shù)據(jù)元素變動比較大的情形亭罪,而且不存在隊列滿產(chǎn)生溢出的問題;而且如果程序中需要使用多個隊列歼秽,最好使用鏈式隊列应役,這樣不會出現(xiàn)存儲分配不合理和“溢出”的情形

鏈式隊列的操作

鏈式隊列的初始化

void InitQueue(LinkQueue &Q){
    Q.front = Q.rear=(LinkNode *)malloc(sizeof(LinkNode));  //建立頭結(jié)點
    Q.front->next = NULL;   //初始為空
}

判鏈式隊列為空

bool IsEmpty(LinkQueue Q){
    if (Q.front == Q.rear)
        return true;
    else
        return false;
}

入隊操作

void EnQueue(LinkQueue &Q,Elemtype x){
    //不用判斷是否為滿,因為鏈式隊列不會滿
    LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
    s->data = x;
    s->next = NULL;
    Q.rear->next = s;
    Q.rear = s;
}

出隊操作

bool DeQueue(LinkQueue &Q,ElemType &x){
    if (Q.front == Q.rear)
        return false;   //判斷鏈式隊列是否為空
    LinkNode *p = Q.front->next;
    x = p->data;
    Q.front->next = p->next;
    if (Q.rear == p)
        Q.rear = Q.front;   //如果原隊列只有一個結(jié)點燥筷,則刪除后隊列為空
    free(p);
    return true;
}

雙端隊列

雙端隊列是指允許兩端都可以進行入隊和出隊操作的隊列箩祥;其元素的結(jié)構(gòu)仍然是線性結(jié)構(gòu),將隊列的兩端分別稱為前端和后端肆氓;兩端都可以出隊或者入隊

輸出受限的雙端隊列:允許在一端進行插入和刪除袍祖,但在另一端只允許進行插入

輸入受限的雙端隊列:允許在一段進行插入和刪除,但在另一端只允許進行刪除

若限定雙端隊列從某個端點插入的元素只能從該端點進行刪除谢揪,則該雙端隊列退化成兩個棧底相臨接的棧

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蕉陋,一起剝皮案震驚了整個濱河市捐凭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凳鬓,老刑警劉巖茁肠,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缩举,居然都是意外死亡垦梆,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門蚁孔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來奶赔,“玉大人,你說我怎么就攤上這事杠氢≌拘蹋” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵鼻百,是天一觀的道長绞旅。 經(jīng)常有香客問我,道長温艇,這世上最難降的妖魔是什么因悲? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮勺爱,結(jié)果婚禮上晃琳,老公的妹妹穿的比我還像新娘。我一直安慰自己琐鲁,他們只是感情好卫旱,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著围段,像睡著了一般顾翼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奈泪,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天适贸,我揣著相機與錄音,去河邊找鬼涝桅。 笑死拜姿,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的冯遂。 我是一名探鬼主播蕊肥,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼债蜜!你這毒婦竟也來了晴埂?” 一聲冷哼從身側(cè)響起究反,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎儒洛,沒想到半個月后精耐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡琅锻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年卦停,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恼蓬。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡惊完,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出处硬,到底是詐尸還是另有隱情小槐,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布荷辕,位于F島的核電站凿跳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏疮方。R本人自食惡果不足惜控嗜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望骡显。 院中可真熱鬧疆栏,春花似錦、人聲如沸惫谤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽石挂。三九已至博助,卻和暖如春险污,著一層夾襖步出監(jiān)牢的瞬間痹愚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工蛔糯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留拯腮,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓蚁飒,卻偏偏與公主長得像动壤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淮逻,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345