數據結構-隊列


 

 

 

 

一、  隊列的定義

  1. 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. 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");                                   

       }

}

  1. 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;
            }
        }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM