c語言描述-鏈式隊列與循環隊列


我真的不喜歡寫代碼

隊列的特點

  • 先進先出,即只能從隊尾插入元素,從隊頭刪除元素

隊列的鏈式存儲結構

#include<stdio.h>
#include <stdlib.h>
#include<malloc.h>
typedef struct QNode
{
    int date;
    struct QNode *next;
}QNode ,*QueuePtr;

typedef  struct
{
    int size; //記錄隊列長度
    QueuePtr front; //頭指針
    QueuePtr rear;  //尾指針
}LinkQueue;
//初始化
void InitQueue(LinkQueue *Q)
{
    Q->front=Q->rear=(QNode *)malloc(sizeof(QNode));
    if(!Q->front)
      exit(0);
    Q->rear->next=NULL;
    Q->size=0;
}
//在隊尾插入元素
void InsertQueue(LinkQueue *Q,int e)
{
    QNode *p;
    p=(QueuePtr)malloc(sizeof(QNode));
    if(p==NULL)
      exit(0);
    p->date=e;
    Q->rear->next=p;
    Q->rear=p;
    Q->rear->next=NULL;
    Q->size++;
}
//刪除隊頭元素
void Pop_Queue(LinkQueue *Q)
{
    Q->front=Q->front->next;
    free(Q->front);
    Q->size--;
}
//向隊列輸入數據
void Push_Queue(LinkQueue *Q)
{
    int e;
    QNode *p=NULL;
    printf("請輸入數據:\n");
    for(int i=0;;i++)  //
    {
        scanf("%d",&e);
        if(Q->size==0)  //當插入第一個元素時
        {
            Q->front->date=e;  
            Q->rear=Q->front;  //頭尾指針都指向第一個結點
            Q->size++;
        }
        else  
        {
            p=(QueuePtr)malloc(sizeof(QNode));
            if(!p)
              exit(0);
            p->date=e;  
            Q->rear->next=p;
            Q->rear=p;
            Q->rear->next=NULL;
            Q->size++; 
        }
        if(getchar()=='\n')
            break;
    }
}
//打印隊列元素
void ShowQueue(LinkQueue *Q)
{
    printf("隊列內的元素為:\n");
    int e;
    QNode *p;
    p=Q->front;
    for(int i=0;i<Q->size;i++)
    {
        e=p->date;
        printf("%d ",e);
        p=p->next;
    }
    printf("\n");
}

int main()
{
    LinkQueue Q,*p;
    p=&Q;
    Push_Queue(p);
    ShowQueue(p);
    InsertQueue(p, 7);
    ShowQueue(p);
    Pop_Queue(p);
    ShowQueue(p);
}
/* 運行結果
請輸入數據:
1 2 3 4 5 6
隊列內的元素為:
1 2 3 4 5 6 
隊列內的元素為:
1 2 3 4 5 6 7 
隊列內的元素為:
2 3 4 5 6 7 
Program ended with exit code: 0
*/

隊列的順序存儲結構---循環隊列

為什么要實現循環隊列圖片來自嚴蔚敏的數據結構):

上圖是隊列的普通順序存儲,隊列存入數據后,每刪除一個元素,front指針都會上移,則front上一個指向的空間就會被浪費,由此引入循環隊列;

循環隊列的實現原理:

上圖即為循環隊列的示意圖;由圖片可知,當front等於rear時,隊列可能為空,也可能滿,解決辦法有兩種辦法,一是定義一個整型數據記錄元素個數;另一種辦法是犧牲一個存儲空間,當(rear+1)%MIXSIEZ==front時為滿;下面討論第二種方法;

實現過程:

  • 插入與刪除時,指針均是在循環鏈表中順時針移動;
  • 插入一個元素時,rear=(rear+1)%MIXSIZE,即向后移動一位;
  • 刪除一個元素時,front=(front+1)%MIXSIZE,即向后移動一位;
  • 判斷隊列為滿:(rear+1)%MIXSIEZ==front

解釋:之所以用(rear+1)%MIXSIEZfront而不用(rear+1)front來判斷隊列是否為滿,是因為,隊列在進行一系列插入與刪除操作后rear可能會小於front,如上圖,5過了之后又回到0,用取模的方法可以解決這個問題,front=(front+1)%MIXSIZE與rear=(rear+1)%MIXSIZE也是同理;

代碼實現:

#include<stdio.h>
#include <stdlib.h>
#include<malloc.h>
#define MIXSIZE 100   //最大存儲空間

typedef struct QNode
{
    int size;  
    int front;
    int rear;
    int *base;
    
}QNode;

//初始化
void InitQueue(QNode *Q)
{
    Q->base=(int *)malloc(MIXSIZE*sizeof(int));
    Q->front=Q->rear=0;
    Q->size=MIXSIZE;
}
//插入
void InsertQueue(QNode *Q,int e)
{
   if((Q->rear+1)%MIXSIZE==Q->front)
        printf("隊列已滿\n");
    Q->base[Q->rear]=e;
    Q->rear=(Q->rear+1)%MIXSIZE;
}
//刪除
void Pop_Queue(QNode *Q)
{
    int e;
    e=Q->base[Q->front++];
}
//輸入元素
void Push_Queue(QNode *Q)
{
    int e;
    printf("請輸入元素:\n");
    for(int i=0;;i++)
    {
        scanf("%d",&e);
        Q->base[Q->rear]=e;
        Q->rear=(Q->rear+1)%MIXSIZE;
        if(getchar()=='\n')  //按回車鍵結束輸入
            break;
    }
    
}
//打印所以元素
void ShowQueue(QNode *Q)
{
    int e;
    int t=Q->front;
    while(t!=Q->rear)
    {
        e=Q->base[t];
        printf("%d ",e);
        t=(t+1)%MIXSIZE;
    }
    printf("\n");
}

int main()
{
    QNode Q,*p;
    p=&Q;
    InitQueue(p);
    Push_Queue(p);
    ShowQueue(p);
    InsertQueue(p,8);
    ShowQueue(p);
    Pop_Queue(p);
    ShowQueue(p);
}
/* 運行結果
請輸入元素:
1 2 3 4 5
1 2 3 4 5 
1 2 3 4 5 8 
2 3 4 5 8 
Program ended with exit code: 0
*/


免責聲明!

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



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