【數(shù)據(jù)結(jié)構(gòu)】棧和隊列之隊列

一吱七、隊列的定義

【定義】:隊列(queue)是只允許在一端進(jìn)行插入操作埋心,而在另一端進(jìn)行刪除操作的線性表。
【特征】:先進(jìn)先出(First In First Out,簡稱FIFO)的線性表(與棧相反)迫肖。允許插入的一端稱為隊尾锅劝,允許刪除的一端稱為隊頭
【應(yīng)用】:隊列在程序設(shè)計中使用非常頻繁蟆湖。比如實現(xiàn)鍵盤進(jìn)行各種字母或數(shù)字的輸入故爵,到顯示器上的輸出等先進(jìn)先出功能。

隊列


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

線性表有順序存儲和鏈?zhǔn)酱鎯Τ砑瑮:完犃幸彩蔷€性表,所以也存在這兩種存儲方式饥瓷。

隊列的順序存儲的不足

隊列元素的出隊在隊頭剥纷,即下標(biāo)為0的位置,也就意味著呢铆,隊列中的所有元素都得向前一定晦鞋,以保證隊列的隊頭位置不為空,時間復(fù)雜度為O(n).

并且隊列的順序存儲結(jié)構(gòu)還會帶來假溢出等問題棺克。

多以引入了循環(huán)隊列

循環(huán)隊列

循環(huán)隊列就是隊列的頭尾相接悠垛,屬于順序存儲結(jié)構(gòu)。
循環(huán)隊列中的幾個特點(diǎn):

  • 隊空的判斷條件:front == rear;
  • 設(shè)隊列的最大存儲空間為MAXSIZE,入隊操作是娜谊,rear需要加1后移一位确买,賦值語句為:rear = (rear + 1) % MAXSIZE,出隊操作,front加1后移的賦值語句:front = (front + 1) % MAXSIZE
完整代碼:
#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 20

typedef int Status;
typedef int QElemType;

typedef struct {
    QElemType data[MAXSIZE]; //用于存放分配的基地址
    
    int front; // 頭指針
    int rear;  // 尾指針
}SqQueue;

/**
 * 1.初始化隊列
 */
Status InitQueue(SqQueue * Q){
    
    Q->front = 0;
    Q->rear = 0;
    return OK;
}

/**
 * 2.獲取隊列長度
 */
int QueueLength(SqQueue Q){
    return (Q.rear - Q.front + MAXSIZE) % MAXSIZE;
}

/**
 * 3.入棧操作
 */
Status InsertQueue(SqQueue * Q, QElemType e){
    
    if ((Q->rear + 1) % MAXSIZE == Q->front) return ERROR;  // 隊滿
    
    Q->data[Q->rear] = e; // 將元素e賦值給隊尾
    Q->rear = (Q->rear + 1) % MAXSIZE; //rear指針后移一個位置
    
    return OK;
}

/**
 * 4.出棧操作
 */
Status DeleteQueue(SqQueue * Q, QElemType *e){
    
    if (Q->front == Q->rear) return ERROR; // 隊空
    
    *e = Q->data[Q->front];  // 將對頭元素賦值給e
    Q->front = (Q->front + 1) % MAXSIZE;  // front指針后移一個位置
    
    return OK;
}

三纱皆、隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu)(鏈隊列)

隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu)湾趾,其實就是線性表的單鏈表,只不過它只能尾進(jìn)頭出而已派草,簡稱鏈隊列搀缠。

1.隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu)定義

代碼實現(xiàn)
typedef int Status;
typedef int QElemType;

typedef struct QNode{ /* 結(jié)點(diǎn)結(jié)構(gòu) */
    QElemType  data;
    struct QNode * next;
}QNode, *QueuePrt;

typedef struct { /* 隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu) */
    QueuePrt front,rear; // 隊頭、隊尾指針
}LinkQueue;

隊頭指針指向鏈隊列的頭結(jié)點(diǎn)近迁,尾指針指向終端結(jié)點(diǎn)艺普。(頭結(jié)點(diǎn)不是必要的,但是加上了可以方便操作)
空隊列frontrear都指向頭結(jié)點(diǎn)鉴竭。

鏈隊列

2.隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu) - 創(chuàng)建一個隊列

步驟:

  • 在內(nèi)存中創(chuàng)建一個頭結(jié)點(diǎn)歧譬。
  • 將隊列的頭指針和尾指針都指向這個生成的頭結(jié)點(diǎn)。(因為此時為空隊列)
代碼實現(xiàn):
/**
 * 鏈隊列的創(chuàng)建
 */
Status InitQueue(LinkQueue * Q){
    
    Q->front = Q->rear = (QueuePrt)malloc(sizeof(QNode));
    
    if (!Q->front) exit(0);
    
    Q->front->next = NULL;
    
    return OK;
}

3.隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu) - 插入操作

入隊操作搏存,其實就是在鏈表尾部插入結(jié)點(diǎn)缴罗。


入隊操作

代碼實現(xiàn):

/**
 * 入隊操作
 */
Status InsertQueue(LinkQueue * Q, QElemType e){
    
    QueuePrt s = (QueuePrt)malloc(sizeof(QNode));
    
    if (!s) exit(0);  // 存儲分配失敗
    
    s->data = e;
    s->next = NULL;
    Q->rear->next = s;  // 把擁有元素e的新節(jié)點(diǎn)賦值給原隊尾結(jié)點(diǎn)的后繼
    Q->rear = s;  // 把當(dāng)前s設(shè)置成隊尾結(jié)點(diǎn),rear指向s
    
    return OK;
}

4.隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu) - 出隊操作

出隊操作是將隊列中的第一個元素移出祭埂,隊頭指針不發(fā)生改變面氓,改變頭結(jié)點(diǎn)的next指針即可兵钮。
代碼:

/**
 * 出隊操作
 */
Status DeleteQueue(LinkQueue * Q, QElemType *e){
    
    QueuePrt p;
    
    if (Q->front == Q->rear) return ERROR; // 空隊列
    
    p = Q->front->next;  // 將欲刪除的隊頭結(jié)點(diǎn)暫存給p
    *e = p->data; // 將欲刪除的隊頭結(jié)點(diǎn)賦值給e
    Q->front->next = p->next; // 將原隊頭結(jié)點(diǎn)后繼p->next賦值給頭結(jié)點(diǎn)后繼
    
    if (Q->rear == p) { // 若隊列只有一個元素,則刪除后將rear指向頭結(jié)點(diǎn)
        Q->rear = Q->front;
    }
    
    free(p);
    
    return OK;
}

5.隊列的鏈?zhǔn)酱鎯Y(jié)構(gòu) - 銷毀隊列

由于鏈度列建立在內(nèi)存的動態(tài)區(qū)舌界,因此當(dāng)一個隊列不再有用的時候掘譬,應(yīng)該把它及時銷毀掉,以免過多的占用內(nèi)存空間呻拌。

/**
 * 銷毀隊列
 */
Status DestoryQueue(LinkQueue * Q){
    
    while (Q->front) {
        Q->rear = Q->front->next;
        free(Q->front);
        Q->front = Q->rear;
    }
    return OK;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末葱轩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子藐握,更是在濱河造成了極大的恐慌靴拱,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猾普,死亡現(xiàn)場離奇詭異袜炕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)初家,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進(jìn)店門偎窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人溜在,你說我怎么就攤上這事陌知。” “怎么了掖肋?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵仆葡,是天一觀的道長。 經(jīng)常有香客問我志笼,道長浙芙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任籽腕,我火速辦了婚禮,結(jié)果婚禮上纸俭,老公的妹妹穿的比我還像新娘皇耗。我一直安慰自己,他們只是感情好揍很,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布郎楼。 她就那樣靜靜地躺著,像睡著了一般窒悔。 火紅的嫁衣襯著肌膚如雪呜袁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天简珠,我揣著相機(jī)與錄音阶界,去河邊找鬼虹钮。 笑死,一個胖子當(dāng)著我的面吹牛膘融,可吹牛的內(nèi)容都是我干的芙粱。 我是一名探鬼主播,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼氧映,長吁一口氣:“原來是場噩夢啊……” “哼春畔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起岛都,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤律姨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后臼疫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體择份,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年多矮,在試婚紗的時候發(fā)現(xiàn)自己被綠了缓淹。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡塔逃,死狀恐怖讯壶,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情湾盗,我是刑警寧澤伏蚊,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布,位于F島的核電站格粪,受9級特大地震影響躏吊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜帐萎,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一比伏、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧疆导,春花似錦赁项、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至败富,卻和暖如春悔醋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背兽叮。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工芬骄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猾愿,地道東北人。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓德玫,卻偏偏與公主長得像匪蟀,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宰僧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容