循環隊列–C語言實現–數據結構

循環隊列–C語言實現–數據結構


目錄


(一) 要求

假設以數組sequ[m]存放循環隊列的元素,同時設變量rear和quelen 分別指示循環隊列中隊尾元素的位置和內含元素的個數。編寫實現該循環隊列的入隊和出隊操作的算法。提示:隊空的條件:sq->quelen==0;隊滿的條件:sq->quelen==m。


(二) 循環隊列

定義:爲充分利用向量空間,克服”假溢出”現象的方法是:將向量空間想象爲一個首尾相接的圓環,並稱這種向量爲循環向量。存儲在其中的隊列稱爲循環隊列(Circular Queue)。這種循環隊列可以以單鏈表的方式來在實際編程應用中來實現, 當然也可以利用順序表來實現。順序表就是我們熟悉的數組 eg. sun[]
回顧:我們再來回顧一下關於順序隊列的重要知識點。隊列通常與棧對應,棧是一種後進先出的單端(尾端)處理的數據結構;那麼與之對應的隊列是一種先進先出的雙端(頭尾兩端)的數據結構。隊列的特點就是在一段進行入隊(存儲數據)操作,在另一端進行出隊(刪除數據)操作。
爲什麼設計循環隊列:大家在處理隊列的時候,會遇到如下情況。例如說:我們的隊列空間能夠容納1000個元素。首先,格格入隊1000個元素,隊列上溢,此時爲“真溢出”。那麼現在我們進行出隊操作,我們一直出隊,一直出隊, 知道1000個元素全部被刪除,此時我們發現隊列仍然處於“上溢”狀態,why? 其實原因很簡單,在非循環隊列當中,無論我們的front指(偏移)到哪裏,只要我們的rear指(偏移)向上闕,那麼隊列就是“滿溢”的。這就造成了空間明明還被佔據着,但是隊列卻已經無用武之地的窘境。對於空間有限的計算機來說,這無疑是一種浪費。也不是一個優秀的程序猿想要看到的。所以在這種情況下,循環隊列誕生了。循環隊列當中的“滿溢”只有一種情況,那就是所有數據空降都被佔領了。而不會存在非循環隊列當中的“假溢出”現象。


我們所常見的順序循環隊列通常有兩種數據結構。

結構一

typedef struct
{
    datatype sequ[m];
    //sequ[]爲我們所建立的順序表(sequence)
    int  front,rear;
    //front表示隊列頭的偏移量,rear表示隊列的尾的偏移量
}qu;//qu是隊列(queue)的縮寫

這裏寫圖片描述

結構二

typedef struct
{
    datatype sequ[m];
    //sequ[]爲我們所建立的順序表(sequence)
    int  rear, quelen;
    //rear表示隊列的尾的偏移量,quelen表示的是隊列中元素的個數
}qu;//qu是隊列(queue)的縮寫

那通過觀察這兩種機構我們能夠很容易的發現,數據結構並不是固定的。我們覺得那種算法比較更合理,我們覺得哪種數據結構方便我們設計算法,那麼我們就建立哪種數據結構。在本文當中,我們採用第二種數據結構。顯而易見的是,當我們採用第二種數據結構時,我們建立的一個隊列指針(qu*sq)隊空的條件:sq->quelen==0;隊滿的條件:sq->quelen==m。


(三) 循環隊列的算法設計


在上面我們瞭解了循環隊列的數據機構,但是僅僅學會了數據結構還遠遠不夠。我們設計數據結構的目的是爲了更好的存儲數據,並利用數據。下面我們來看一看關於循環隊列我們要掌握哪些最基本的算法(利用數據機構)。


3.1 建立循環隊列

//建立隊
qu* creatqueue();//函數聲明
qu* creatqueue()//函數實現
{
    qu *sq;
    sq=(qu*)malloc(sizeof(qu));
    return sq;  
}

3.2 置空隊列

//置空隊
void setnull(qu*);//函數聲明
void setnull(qu *sq)//函數實現
{
    sq->rear = m - 1;
    sq->quelen = 0;
}

3.3 入隊

//入隊
void enqueue(qu*, datatype);//函數聲明
void enqueue(qu*sq, datatype x)//函數實現
{
    if (sq->quelen == 5)
        printf("Errot! The queue will be overflow! \n");
    else if((sq->rear+1)==m)
    {
        sq->rear = (sq->rear + 1) % m;
        sq->sequ[sq->rear] = x;
        sq->quelen++;
        printf("過5入隊成功!\n");
    }
    else
    {
        sq->rear++;
        sq->sequ[sq->rear] = x;
        sq->quelen++;
        printf("入隊成功!\n");
    }
}

**算法流程圖**


3.4 出隊

//出隊
datatype *dequeue(qu*);//函數聲明
datatype *dequeue(qu*sq)//函數實現
{
    datatype sun=0;
    if (sq->quelen == 0)
    {
        printf("Error! The queue will be under flow!\n");
        return 0;
    }
    else if ((sq->rear + 1) >= sq->quelen)
    {
        sq->quelen--;
        sun = sq->sequ[sq->rear - sq->quelen];
        return(&sun);
    }
    else    //  if(sq->rear < sq->quelen)
    {
        sq->quelen--;
        sun = sq->sequ[sq->rear - sq->quelen + m];
        return(&sun);
    }
}

**算法流程圖**


3.5 打印隊

//打印隊
void print(qu*);//函數聲明
void print(qu*sq)//函數定義
{
    if (sq->quelen == 0)
        printf("Error! The queue is Null!\n");
    else if ((sq->rear + 1) >= sq->quelen)
    {
        int i = sq->rear + 1 - sq->quelen;
        for (i; i <= sq->rear; i++)
            printf("%d   ", sq->sequ[i]);
    }
    else
    {
        int t = sq->rear - sq->quelen + m +1;
        int time = 1;
        for (t; time <= (sq->quelen); time++)
        {
            printf("%d   ", sq->sequ[t]);
            t++;
            if (t == m)
            {
                t = 0;
                continue;
            }
            else
            {
                continue;
            }
        }
    }
    printf("\n");
}

(四) 程序


下面我們來設計一個程序測試我們的數據機構與算法


4.1 程序的結構

**程序結構**


4.2 程序源碼

注意:該程序由Microsoft Visual Studio Enterprise 2015編譯器進行調試。受制於編譯器品牌及版本不同等不可抗因素造成的編譯失敗,請自行調整。

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define m 5

//循環隊列的結構類型定義
typedef int datatype;
typedef struct
{
    datatype sequ[m];
    int  rear, quelen;
}qu;

//函數聲明
qu* creatqueue();
void setnull(qu*);
void enqueue(qu*, datatype);
datatype *dequeue(qu*);
void print(qu*);

//主函數
void main()
{
    qu *sq= creatqueue();

    datatype x, *p;
    int key;

    setnull(sq);
    do
    {
        printf("1.Enter Queue   2.Delete Queue   3.clc display   4.print queue   -1.Quit:");
        scanf_s("%d", &key);
        switch (key)
        {
        case 1:  printf("Enter the Data:"); scanf_s("%d", &x);
            enqueue(sq, x);  break;
        case 2:  p = dequeue(sq);
            if (p != NULL) printf("%d\n", *p);
            break;
        case 3:system("cls"); break;
        case 4:print(sq); break;
        case -1: exit(0);
        }
    } while (1);
}

//建立隊
qu* creatqueue()
{
    qu *sq;
    sq=(qu*)malloc(sizeof(qu));
    return sq;  
}
//置空隊
void setnull(qu *sq)
{
    sq->rear = m - 1;
    sq->quelen = 0;
}

//入隊
void enqueue(qu*sq, datatype x)
{
    if (sq->quelen == 5)
        printf("Errot! The queue will be overflow! \n");
    else if((sq->rear+1)==m)
    {
        sq->rear = (sq->rear + 1) % m;
        sq->sequ[sq->rear] = x;
        sq->quelen++;
        printf("過5入隊成功!\n");
    }
    else
    {
        sq->rear++;
        sq->sequ[sq->rear] = x;
        sq->quelen++;
        printf("入隊成功!\n");
    }
}


//出隊
datatype *dequeue(qu*sq)
{
    datatype sun=0;
    if (sq->quelen == 0)
    {
        printf("Error! The queue will be under flow!\n");
        return 0;
    }
    else if ((sq->rear + 1) >= sq->quelen)
    {
        sq->quelen--;
        sun = sq->sequ[sq->rear - sq->quelen];
        return(&sun);
    }
    else    //  if(sq->rear < sq->quelen)
    {
        sq->quelen--;
        sun = sq->sequ[sq->rear - sq->quelen + m];
        return(&sun);
    }
}

//打印隊列
void print(qu*sq)
{
    if (sq->quelen == 0)
        printf("Error! The queue is Null!\n");
    else if ((sq->rear + 1) >= sq->quelen)
    {
        int i = sq->rear + 1 - sq->quelen;
        for (i; i <= sq->rear; i++)
            printf("%d   ", sq->sequ[i]);
    }
    else
    {
        int t = sq->rear - sq->quelen + m +1;
        int time = 1;
        for (t; time <= (sq->quelen); time++)
        {
            printf("%d   ", sq->sequ[t]);
            t++;
            if (t == m)
            {
                t = 0;
                continue;
            }
            else
            {
                continue;
            }
        }
    }
    printf("\n");
}


(五) 程序測試


5.1 入隊列

**入隊列及上溢檢測**


5.2 出隊列

出隊列及下溢檢測


5.3 打印隊列

前面已經用到了打印隊列,所以格格不再贅述,大家由5.2&5.3可知打印隊列是成功的。


(六) 源程序及封裝軟件下載

下載地址


格格是一枚智能專業的本科在校生,很願意和各位大佬交流。如果大家有願意交朋友的,可以加格格的QQ:446019725,聲明是CSDN即可。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章