循環隊列–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即可。