數據結構與算法 —— 隊列的鏈式存儲結構

一.概述

隊列是一種只允許咋一端進行操作(插入,刪除)的線性表,與棧相比,棧是一種先進後出(Fast In Last Out)的形式,隊列則是先進先出(Fast In Fast Out),就像我們日常生活中的排隊一樣(大家都很有素質)。
在這裏插入圖片描述

二.結點定義

使用鏈式存儲結構的方式,結點的定義:

typedef struct QNode {
    ElemType data;
    struct QNode *next;
}QNode,*QueuePtr;

typedef struct {
    QueuePtr front,rear; //隊頭,隊尾指針
}LinkQueue;

爲了方便操作,通常,會添加一個不用來存儲數據的頭結點:
在這裏插入圖片描述

二. 初始化隊列

通過前面所說,創建一個隊列,可以先創建一個頭結點,再將我們定義好的頭指針與尾指針指向頭結點即可:

int InitQueue(LinkQueue *q)
{
    q->front = q->rear = (QueuePtr)malloc(sizeof(QNode));
    if(!q->front)
    {
        printf("Malloc failure\n");
        return -1;
    }

    q->front->next = NULL;
}

三. 入列

聯想隊列的存儲結構,隊列是從隊尾插入,當有一個結點p想要進入隊列,則需要下面的幾個步驟:
在這裏插入圖片描述
代碼:

void InsetQueue(LinkQueue *q,ElemType e)  //插入元素
{     
    QueuePtr p;
    p = (QueuePtr)malloc(sizeof(QNode));
      
    if(!p)
    { 
        printf("Malloc failure\n");
        exit(0);
    } 
      
    p->data = e;
    p->next = NULL;
    q->rear->next = p;
    q->rear = p;
      
}     

四. 出列

獲取到第一個結點的值,將頭指針指向第二個結點:
在這裏插入圖片描述
需要注意兩點,一是要先判斷鏈表是否爲空,二是判斷出列一個元素後,鏈表是否爲空:

void DeleteQueue(LinkQueue *q,ElemType *e)
{      
    if(q->front == q->rear)
    {  
        printf("鏈表當前爲空\n");
        return;
    }  
       
    QueuePtr p;
    p = q->front->next;
    *e = p->data;
    q->front->next = p->next;  //指向第二個結點
   
    if(q->rear == p)
    {
        q->rear = q->front;
        printf("隊列最後一個元素出列,隊列成爲空隊列\n");
    }
    free(p);
   
}      

五. 銷燬隊列

如果隊列過長將會佔用極大一部風存儲空間,在使用完時需要及時銷燬從而釋放內存,首先,將rear指針指向front->next,銷燬front,再將front指向rear,rear再次指向front->next,直達最後都爲NULL則結束:
在這裏插入圖片描述
代碼:

void DestroyQueue(LinkQueue *q)
{  
    while(q->front)
    {
        q->rear = q->front->next;
        free(q->front);
        q->front = q->rear;
    }
    printf("鏈表已銷燬\n");
}      

六. 運行程序

源碼:

/*********************************************************************************
 *      Copyright:  (C) 2020 Xiao yang IoT System Studio
 *                  All rights reserved.
 *
 *       Filename:  Queue.c
 *    Description:  This file 
 *                 
 *        Version:  1.0.0(06/20/2020)
 *         Author:  Lu Xiaoyang <[email protected]>
 *      ChangeLog:  1, Release initial version on "06/20/2020 09:06:49 AM"
 *                 
 ********************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define ElemType int

typedef struct QNode {
    ElemType data;
    struct QNode *next;
}QNode,*QueuePtr;

typedef struct {
    QueuePtr front,rear; //隊頭,隊尾指針
}LinkQueue;

void InitQueue(LinkQueue *q)
{
    q->front = q->rear = (QueuePtr)malloc(sizeof(QNode));
    if(!q)
    {
        printf("Malloc failure\n");
        exit(0);
    }

    q->front->next = NULL;
}

void InsertQueue(LinkQueue *q,ElemType e)
{
    QueuePtr p;
    p = (QueuePtr)malloc(sizeof(QNode));

    if(!p)
    {
        printf("Malloc failure\n");
        exit(0);
    }

    p->data = e;
    p->next = NULL;
    q->rear->next = p;
    q->rear = p;
    
}

void DeleteQueue(LinkQueue *q,ElemType *e)
{
    if(q->front == q->rear)
    {
        printf("鏈表當前爲空\n");
        return;
    }

    QueuePtr p;
    p = q->front->next;
    *e = p->data;
    q->front->next = p->next;  //指向第二個結點

    if(q->rear == p)
    {
        q->rear = q->front;
        printf("隊列最後一個元素出列,隊列成爲空隊列\n");
    }
    free(p);
}

void DestroyQueue(LinkQueue *q)
{
    while(q->front)
    {
        q->rear = q->front->next;
        free(q->front);
        q->front = q->rear;
    }
    printf("鏈表已銷燬\n");
}

int main(int argc, char *argv[])
{
    int i = 0;
    int temp;

    LinkQueue Que;
    InitQueue(&Que);

    for(i = 1; i <=10; i++)
    {
        InsertQueue(&Que,i);
    }

    for(i = 1; i<= 10; i++)
    {
        DeleteQueue(&Que,&temp);
        printf("獲取到鏈表元素%d \n",temp);
    }

    DestroyQueue(&Que);

    return 0;
}

運行結果:
在這裏插入圖片描述

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