一、 隊列的定義
- 1. 為什么要學習隊列?
你們在用電腦時有沒有經歷,機器有時會處於疑似死機的狀態,鼠標點什么似乎都沒用,雙擊任何快捷方式都不動彈。就當你失去耐心,打算rest時。突然他像酒醒了一樣,把你剛才點擊的所有操作全部按順序執行一遍。這其實是因為操作系統中的多個程序因需要通過一個通道輸出,而按先后次序排隊等待造成的。
再比如向移動、聯通、電信等客服電話,客服人員與客戶相比總是少數,在所有的客服人員都占線的情況下,客戶會被要求等待,直到有某個客戶人員空下來,才能讓最先等待的客戶接通電話。這里也是將所有當前打客服電話的客戶進行排隊處理。
操作系統和客服系統中,都是應用了一種數據結構來實現剛才提到的先進先出的排隊功能,這就是隊列。
隊列(queue)是只允許在一端進行插入操作,而在另一端進行刪除操作的線性表。
隊列是一種先進先出(First in First Out)的線性表,簡稱FIFO。允許插入的一端稱為隊尾,允許刪除的一端稱為隊頭。假設隊列是q=(a1,a2,…,an),那么a1就是隊頭元素,而an是隊尾元素。這樣我們就可以刪除時,總是從a1開始,而插入時,列在最后。這也比較符合我們通常生活中的習慣,排在第一個的優先出列,最后來的當然在隊伍的最后。
隊列在設計程序中用的非常頻繁。比如用鍵盤進行各種字母或數字的輸入,到顯示器如記事本軟件上的輸出,其實就是對列的典型應用,假如你本來和女友聊天,想表達你是我的上帝,輸入的是god,而屏幕上卻顯示出了dog發了出去,這真是要氣死人了
一、 隊列的抽象數據類型
同樣是線性表,隊列也有類似線性表的各種操作,不同的就是插入數據只能在隊尾進行,刪除數據只能在隊頭進行。
一、 ACM算法:隊列的實現
隊列的定義:
#include "stdio.h"
#define MAXSIZE 5 //最大容量是5個元素
struct queue //隊列
{
int a[MAXSIZE]; //隊列元素
int front; //隊頭
int rear; //隊尾
};
- 1. 入隊操作
算法:
步驟一:判斷是否溢出,若溢出給出提示結束程序,否則跳到步驟二
步驟二:輸入入隊的元素
步驟三:將元素存於隊尾處
步驟四:隊尾下標自增
//入隊操作
void enqueue(struct queue *q)
{
int e;
if(q->rear<MAXSIZE-1)
{
printf("請輸入入隊的元素:");
scanf("%d",&e);
q->a[q->rear]=e;
q->rear++;
printf("入隊成功\n");
}
else
{
printf("溢出\n");
}
}
- 2. 出隊操作
算法:
步驟一:判斷是有元素,若無元素則給出提示結束程序,否則跳到步驟二
步驟二:用e接收出隊的元素
步驟三:
步驟四:隊尾下標自增
//出隊操作
void dequeue(struct queue *q)
{
int e;
if(q->front==q->rear)
{
printf("隊空,沒有元素\n");
}
else
{
e=q->a[q->front];
q->front++;
printf("出隊的元素是%d\n",e);
}
}
二、 循環隊列
所以解決假溢出的辦法就是后面滿了,就再從頭開始,也就是頭尾相接的循環。我們把隊列的這種頭尾相接的順序存儲結構稱為循環隊列。
剛才的例子繼續,把它的rear可以改為指向下標為0的位置,這樣就不會造成指針指向不明的問題了。
接着入隊a6,將它放置於下標為0處,rear指針指向下標為1處,若再入隊a7,則rear指針就與front指針重合,同時指向下標為2的位置。
此時問題又出來了,我們剛才說,空入隊列時,front等於rear,現在當隊列滿時,也是front等於rear,那么如何判斷此時的隊列究竟是空還是滿呢?
辦法一是設置一個標致變量flag,當front==rear,且flag=0時時為隊列空,當front==rear,且flag=1時為隊列滿。
辦法二是當隊列空時沒條件就是front=rear,當隊列滿時,我們修改其條件,保留一個元素空間。也就是說,隊
我們重點來討論第二種方法,由於rear可能比front大,也可能比front小,所以盡管他們只相差一個位置是就是滿的情況,但也可能是相差整整一圈,所以若隊列的最大尺寸為QueueSize,那么隊列滿的條件是(rear+1)%QueueSize==front(取模“%”的目的就是為了整合rear與front大小為一個問題)。比如上面這個例子,QueueSize=5中的front=0,而rear=4,(4+1)%5=0,所以此時隊列滿。再比如front=2而rear=1.(1+1)%5=2,所以此時隊列也是滿的。而對於front=2和rear=0,(0+1)%5=1,1≠2,所以此時隊列並沒有滿。
另外,當rear>front時,此時隊列的長度為rear—front.但當rear<front時,隊列長度分為兩端,一端是QueueSize—front,另一端是0+rear,加在一起,隊列長度為rear—front+QueueSize.因此通用的計算機隊列隊列長度公式為:
(rear—front+QueueSize)%QueueSize
有了這些講解,現在實現循環隊列的代碼就不難了。循環隊列的順序存儲結構代碼如下:
#include "stdio.h" #include "stdlib.h" #define MAX 6 struct stack{ int a[MAX]; int rear; int font; }s; void main() { int bh; int e,i; s.rear=0; s.font=0; printf("\n1.入隊\n2.出對\n3.打印\n4.退出\n"); for(;;){ scanf("%d",&bh); switch(bh){ case 1: if((s.rear+1)%MAX==s.font){ printf("溢出\n"); break; }else{ printf("輸入入隊數據:"); scanf("%d",&e); s.a[s.rear]=e;/* 人為浪費一個空間 */ s.rear=(s.rear+1)%MAX;//尾部加一 } break; case 2: if(s.rear==s.font){ printf("隊列為空!\n"); break; }else{ e=s.a[s.font]; s.font=(s.font+1)%MAX; printf("出隊的元素是%d\n",e); } break; case 3: if(s.rear==s.font){ printf("隊列為空!\n"); break; } if(s.rear>s.font){ for(i=s.font;i<s.rear;i++){ printf("%d ",s.a[i]); } }else{ /* for(i=s.font;i<MAX;i++){ printf("%d ",s.a[i]); } for(i=0;i<s.rear;i++){ printf("%d ",s.a[i]); }*/ for(i=s.font;i!=s.rear;i=(i+1)%MAX){ printf("%d ",s.a[i]); }//兩個都可以用這個 } break; case 0: exit(0); break; default : printf("輸入功能編號有誤!\n"); } } }
循環隊列plus版本
/* Note:Your choice is C IDE */ #include "stdio.h" #define MAX 20 struct student { int age[MAX]; int top;//記錄頭節點 int rear;//記錄尾節點 }; void add(struct student *s) { int a; printf("請輸入您要添加的數字\n"); scanf("%d",&a); if(s->rear<MAX) { s->age[s->rear]=a; if(s->rear>MAX) { s->rear=0; }else{ s->rear++; } } } void delete(struct student *s) { if(s->rear==s->top) { printf("**沒有元素**\n"); }else{ if(s->top>MAX) { s->top=0; }else{ s->top++; } } } void menu() { printf("********************\n"); printf("**進隊**************\n"); printf("**出隊**************\n"); printf("**顯示隊列**********\n"); printf("********************\n"); } void main() { struct student s; int bh,i; s.rear=0; s.top=0; menu(); while(1) { printf("請輸入選項"); scanf("%d",&bh); switch(bh) { case 1: add(&s); break; case 2: delete(&s); break; case 3: for(i=s.top;i!=s.rear;i=(i+1)%MAX){ printf("|%d",s.age[i]); } printf("\n"); break; case 0: exit(0); break; default: printf("您輸入的選項有誤!!!\n"); break; } } }