數(shù)據(jù)結(jié)構(gòu)與算法06——隊列之循環(huán)隊列

隊列

與棧不同狸臣,他就是現(xiàn)實中排隊一樣,講究先來后到粉寞,即 先進(jìn)先出尼荆。

打個比方,你告訴朋友我們做地鐵去西湖唧垦,你輸入 "s-u-b", 如果按照棧 先入后出后入先出 的方式捅儒,朋友會收到 b-u-s, what?有地鐵振亮,我們干嘛做兩個小時的汽車巧还??坊秸? 隊列就可以讓朋友按你輸入的順序依次收到 s-u-b 麸祷。

簡單的看一下隊列,是線性結(jié)構(gòu)褒搔,想到什么阶牍?非常熟悉的 線性表 喷面,有兩種存儲結(jié)構(gòu),順序存儲和鏈?zhǔn)酱鎯?/strong>荸恕。
我們今天先講一講隊列的順序存儲結(jié)構(gòu)——循環(huán)隊列

先看一種隊列

image

假設(shè)開辟一個存儲大小為5個內(nèi)存單元的隊列

我列舉了四種狀態(tài) :空隊列乖酬,入隊死相,入隊到隊滿融求,刪除只剩一個元素。
先看前三種:當(dāng)為空隊列時算撮,front和rear都指向了同一個元素生宛,判為空;當(dāng)入隊時肮柜,rear向后移動陷舅,指向新元素,當(dāng)出隊時审洞,front指向下一個元素莱睁;當(dāng)front=0,rear=4時芒澜,整隊滿仰剿,操作貌似沒有問題。這一切看似完美痴晦。

但是南吮,,誊酌,如果如下圖部凑,出隊到只剩最后一個元素,front和rear又都指向了一個同元素碧浊,而且僅在隊尾涂邀,又要認(rèn)為隊列為空?不可能啊箱锐,明明最后一塊存儲單元還有一個元素比勉,而且卻不能繼續(xù)入隊新元素,超出了存儲范圍瑞躺,如果要繼續(xù)利用前面出隊的空余空間敷搪,又該怎么用?

image

如果 我們把隊列設(shè)計成下面這樣:

image

哈哈幢哨,循環(huán)了赡勘。隊尾rear指向下一個位置,而不是當(dāng)前的隊尾元素捞镰。

  • 如圖(b)所示闸与,a先入隊 b再入隊 C再入隊 毙替,rear指向C后面的位置。
  • 如圖(c)所示践樱,隊首元素a出隊厂画,front指向下一個隊首b,但是此時front=1拷邢,而不再是從0開始袱院,一邊出隊一邊入隊,那么front的位置就會是0瞭稼,1忽洛,2,3环肘,4欲虚,5 然后利用取模運算front = (front+1) % max,front又回到0,然后1悔雹。复哆。。腌零。梯找。 使得每次front的位置可以在隊尾之后繼續(xù)回到標(biāo)號從0的位置繼續(xù)往后走,周期循環(huán)莱没。同理初肉,rear,新增到rear = 5時饰躲,也利用取模運算牙咏,新的數(shù)據(jù)從標(biāo)號為0開始繼續(xù)入隊,實現(xiàn)循環(huán)隊列嘹裂。
  • 如果隊滿是什么樣妄壶,看下圖

image

????? rear指向的下一個位置是隊首front的b,哇寄狼,還是和之前一樣丁寄,front==rear, 但是我們已經(jīng)用循環(huán)解決當(dāng)只有最后一塊存儲單元有元素而不能再繼續(xù)入隊的問題泊愧。

無礙,我們可以犧牲一個front前的存儲單元伊磺,用來保持隊尾和隊首的距離,來解決最后一個問題:判斷隊滿删咱,(Q.rear+1) % Q.max == Q.front 屑埋, 如果條件成立,意味著空的下一個位置就是隊首front痰滋,此時隊已滿

image

這就是循環(huán)隊列的工作流程

循環(huán)隊列

將上面的過程做一下整理:

  1. 當(dāng)初始化隊列為空時摘能,front = rear = 0续崖;
  2. 入隊,rear+1团搞,指向隊尾的下一個存儲單元严望,為了實現(xiàn)循環(huán)利用取模運算:rear = (rear+1) % max;
  3. 出隊,front+1逻恐,指向下一個隊首像吻,實現(xiàn)循環(huán):front = (front+1) % max;
  4. 判斷隊滿,(Q.rear+1) % Q.max == Q.front

定義

#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OK 1
#define MAXSIZE 20 /* 存儲空間初始分配量 */

typedef int Status;/* Status是函數(shù)的類型,其值是函數(shù)結(jié)果狀態(tài)代碼梢莽,如OK等 */
typedef int ElemType;/* ElemType類型根據(jù)實際情況而定萧豆,這里假設(shè)為int */

/* 隊列結(jié)構(gòu) */
typedef struct
{
    ElemType *data;
    int front;  /* 記錄隊首元素位置 */
    int rear;   /* 記錄對尾元素位置 */
    int max;    /* 記錄開辟內(nèi)存空間的大小 */
}SqQueue;

初始化創(chuàng)建隊列

/// 初始化創(chuàng)建隊列
/// @param Q 隊列指針
/// @param n 指定開辟空間大小奸披,一個空間大小是 sizeof(ElemType)
Status InitQueue(SqQueue *Q, int n)
{
    Q->data = malloc(sizeof(ElemType) * n);
    if (Q->data == NULL) return ERROR;
    
    Q->max = n;
    Q->front = Q->rear = 0;
    
    return OK;
}

獲得元素個數(shù)

/// 獲取隊列元素個數(shù)(包括rear指向的空位置)
/// @param Q 隊列
int GetLength(SqQueue Q)
{
    return (Q.rear - Q.front + Q.max) % Q.max;
}

判斷是不是空

Status QueueEmpty(SqQueue Q)
{
    if (Q.front == Q.rear) {
        return OK;
    }
    return ERROR;
}

隊滿

Status QueueFull(SqQueue Q)
{
    if ((Q.rear+1) % Q.max == Q.front)
    {
        return OK;
    }
    else
    {
        return ERROR;
    }
}

獲得隊首元素

Status GetFront(SqQueue Q, ElemType *e)
{
    if (QueueEmpty(Q) == OK) {
        return ERROR;
    }
    
    *e = Q.data[Q.front];
    return OK;
}

入隊

/// 入隊操作
/// @param Q 隊列
/// @param e 新數(shù)據(jù)
Status EnQueue(SqQueue *Q, ElemType e)
{
    // 判斷隊列有沒有滿
    if (QueueFull(*Q)) return ERROR;
    
    Q->data[Q->rear] = e;
    // 隊尾向后移動昏名,取模運算,超出隊尾阵面,實現(xiàn)循環(huán)繼續(xù)從隊首開始
    Q->rear = (Q->rear+1) % Q->max;
    
    return OK;
}

出隊

/// 出隊列
/// @param Q 隊列
/// @param e 出的元素
Status DeQueue(SqQueue *Q, ElemType *e)
{
    // 判斷對了是不是空
    if (QueueEmpty(*Q) == OK) return ERROR;
    
    *e = Q->data[Q->front];
    // 隊首位置向后移動一位
    Q->front = (Q->front+1) % Q->max;
    
    return OK;
}

遍歷輸出

Status QueuePrint(SqQueue *Q)
{
    /* 從隊首開時輸出轻局,直到對尾 */
    int i = Q->front;
    while (i != Q->rear) {
        printf("%d ",Q->data[i]);
        i = (i+1) % Q->max;
    }
    printf("\n");
    
    return ERROR;
}

測試輸出

指定隊列最大存儲5個單元,方便觀看

int main(int argc, const char * argv[]) {
    
    SqQueue queue;
    InitQueue(&queue, 5);
    
    printf("插入數(shù)據(jù):");
    for (int i = 0; i < 30; i++) {
        EnQueue(&queue, i);
    }
    QueuePrint(&queue);
    
    int e ;
    
    printf("出隊:");
    if (DeQueue(&queue, &e))
    {
        QueuePrint(&queue);
    }
    if (DeQueue(&queue, &e))
    {
        QueuePrint(&queue);
    }
    
    
    int frontE;
    if (GetFront(queue, &frontE)) {
        printf("隊頭:%d\n",frontE);
    }
    
    printf("插入數(shù)據(jù):");
    scanf("%d",&e);
    EnQueue(&queue, e);
    QueuePrint(&queue);
    
    printf("插入數(shù)據(jù):");
    scanf("%d",&e);
    EnQueue(&queue, e);
    QueuePrint(&queue);
    
    printf("插入數(shù)據(jù):");
    scanf("%d",&e);
    EnQueue(&queue, e);
    QueuePrint(&queue);
    
    printf("插入數(shù)據(jù):");
    scanf("%d",&e);
    EnQueue(&queue, e);
    QueuePrint(&queue);
    
    printf("開始清空隊列\(zhòng)n");
    ClearQueue(&queue);
    QueuePrint(&queue);
    
    DestoryQueue(&queue);
    
    return 0;
}
image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末样刷,一起剝皮案震驚了整個濱河市仑扑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌置鼻,老刑警劉巖镇饮,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異箕母,居然都是意外死亡储藐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門嘶是,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钙勃,“玉大人,你說我怎么就攤上這事聂喇∠皆矗” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵希太,是天一觀的道長克饶。 經(jīng)常有香客問我,道長誊辉,這世上最難降的妖魔是什么矾湃? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮芥映,結(jié)果婚禮上洲尊,老公的妹妹穿的比我還像新娘远豺。我一直安慰自己,他們只是感情好坞嘀,可當(dāng)我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布躯护。 她就那樣靜靜地躺著,像睡著了一般丽涩。 火紅的嫁衣襯著肌膚如雪棺滞。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天矢渊,我揣著相機與錄音继准,去河邊找鬼。 笑死矮男,一個胖子當(dāng)著我的面吹牛移必,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毡鉴,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼崔泵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了猪瞬?” 一聲冷哼從身側(cè)響起憎瘸,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎陈瘦,沒想到半個月后幌甘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡痊项,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年锅风,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片线婚。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡遏弱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出塞弊,到底是詐尸還是另有隱情漱逸,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布游沿,位于F島的核電站饰抒,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏诀黍。R本人自食惡果不足惜袋坑,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望眯勾。 院中可真熱鬧枣宫,春花似錦婆誓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至翅娶,卻和暖如春文留,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背竭沫。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工燥翅, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜕提。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓森书,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贯溅。 傳聞我的和親對象是個殘疾皇子拄氯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,713評論 2 354

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