鏈式佇列

Yxw_lp發表於2024-04-26

以連結串列為基礎實現鏈式佇列


/********************************************************************************
 *
 *  file name:  Linked_Queues
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/26
 *  function :  以連結串列為基礎實現鏈式佇列,一般把連結串列頭部作為隊頭,可以實現頭刪,
 *              把連結串列尾部作為隊尾,可以實現尾插。
 *
 *  note     :  None
 *  CopyRight  (c)  2023-2024   yxw18679428019@163.com    All  Right  Reseverd
 *   ****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// 指的是順序棧中的元素的資料型別,使用者可以根據需要進行修改
typedef int DataType_t;

// 構造連結串列的結點,連結串列中所有結點的資料型別應該是相同的
typedef struct Linked_Queues
{
    struct Linked_Queues *next; // 建立一個指標域
    DataType_t data;            // 建立資料域
} LinkQueu_t;

/*******************************************************************************
 *  name     :  LinkQueu_Create
 *  function :  建立一個空鏈式對列,空連結串列應該有一個頭結點,對連結串列進行初始化
 *  argument :  None
 *
 *
 *  retval   :  返回管理順序棧的地址
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/26
 *  note     :  None
 *   ***************************************************************************/
LinkQueu_t *LinkQueu_Create(void)
{
    // 建立一個頭結點並對頭結點申請堆記憶體
    LinkQueu_t *Head = (LinkQueu_t *)calloc(1, sizeof(LinkQueu_t));
    // 判斷申請的堆記憶體是否成功如果失敗直接結束程式
    if (NULL == Head)
    {
        perror("calloc memroy for Head is failed \n");
        exit(-1);
    }

    // 2.對頭結點進行初始化,頭結點是不儲存有效內容的!!!
    Head->next = NULL;

    // 返回頭結點的地址
    return Head;
}

/*******************************************************************************
 *  name     :  LinkQueu_NewNode
 *  function :  建立一個新的結點並對資料域與指標域進行初始化
 *  argument :
 *              @Data :傳入的資料值
 *
 *  retval   :  返回管理順序棧的地址
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/26
 *  note     :  None
 *   ***************************************************************************/

LinkQueu_t *LinkQueu_NewNode(DataType_t Data)
{
    // 建立一個新結點並申請堆記憶體
    LinkQueu_t *New = (LinkQueu_t *)calloc(1, sizeof(LinkQueu_t));
    // 判斷堆記憶體是否申請成功如果申請失敗則直接退出程式
    if (NULL == New)
    {
        perror("calloc memroy for NewNode is failed \n");
        exit(-1);
    }

    // 對新結點的資料域與指標域進行初始化
    New->next = NULL;
    New->data = Data;

    // 返回新結點的地址
    return New;
}

/*******************************************************************************
 *  name     :  LinkQueu_Front
 *  function :  鏈式佇列的入列
 *  argument :
 *              @Head :頭結點的地址
 *              @Data :傳入的資料值
 *  retval   :  true and false
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/26
 *  note     :  None
 *   ***************************************************************************/

bool LinkQueu_Rear(LinkQueu_t *Head, DataType_t Data)
{

    LinkQueu_t *Phead = Head; // 定義一個指標記錄頭結點
    // 建立一個新的結點,
    LinkQueu_t *New = LinkQueu_NewNode(Data);
    if (NULL == New)
    {
        printf("can not insert new node\n");
        return false;
    }
    // 判斷鏈式佇列是否為空
    if (NULL == Head->next)
    {
        Head->next = New; // 如果為空則頭結點的next指標指向新結點
        return true;
    }

    // 遍歷到尾結點
    while (Phead->next)
    {
        Phead = Phead->next;
    }

    // 鏈式佇列為非空
    Phead->next = New; // 尾結點的next指標指向新結點
    return true;
}

/*******************************************************************************
 *  name     :  LinkQueu_Rear
 *  function :  鏈式佇列的出列
 *  argument :
 *              @Head :頭結點的地址
 *
 *  retval   :  返回刪除結點資料域的值
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/26
 *  note     :  None
 *   ***************************************************************************/
DataType_t LinkQueu_Front(LinkQueu_t *Head)
{

    LinkQueu_t *Phead = Head->next; // 定義一個指標記錄首結點
    DataType_t temp;                // 備份首結點資料域的值
    // 判斷鏈式佇列是否為空
    if (Head->next == NULL)
    {
        printf("Linked Queues is empty \n");
        return 0;
    }
    else
    {
        // 鏈式佇列不為空
        if (Phead->next)
        {
            Head->next = Phead->next; // 頭結點的next指標指向首結點的直接後繼
            Phead->next = NULL;       //// 首結點的next指標指向NULL
            temp = Phead->data; 
            free(Phead);        // 釋放首結點的記憶體
        }
        else
        {
            Head->next = NULL;
            free(Phead);
        }
    }
    // 返回刪除結點的值
    return temp;
}

/*******************************************************************************
 *  name     :  LinkQueu_Rear
 *  function :  遍歷結點,並輸出結點的資料域的值
 *  argument :
 *              @Head :頭結點的地址
 *
 *  retval   :  None
 *  author   :  yxw18679428019@163.com
 *  date     :  2024/04/26
 *  note     :  None
 *   ***************************************************************************/
void LinkQueu_Print(LinkQueu_t *Head)
{
    LinkQueu_t *Phead = Head; // 備份頭結點
    while (Phead->next)
    {
        Phead = Phead->next;
        printf("%d\n", Phead->data);
    }
}

int main(void)
{
    LinkQueu_t *Head = LinkQueu_Create();
    LinkQueu_Rear(Head, 1);

    LinkQueu_Rear(Head, 2);
    LinkQueu_Rear(Head, 3);
    LinkQueu_Print(Head);

    LinkQueu_Front(Head);
    LinkQueu_Front(Head);
    LinkQueu_Front(Head);
    LinkQueu_Front(Head);

    LinkQueu_Rear(Head, 3);
    LinkQueu_Print(Head);

    return 0;
}

相關文章