單連結串列構建佇列的介面函式
/*******************************************************************
*
- 檔名稱 : 單連結串列構建佇列的介面函式
- 檔案作者 : mailLinL@163.com
- 建立日期 : 2024/04/26
- 檔案功能 : 對單連結串列迴圈佇列的增刪改查功能的定義
- 注意事項 : None
- CopyRight (c) 2024 mailLinL@163.com All Right Reseverd
- *****************************************************************/
本函式中涉及到的標準C庫
#include <stdlib.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
單連結串列佇列中的結點有效資料型別,使用者可以根據需要進行修改
typedef int DataType_t;
構造連結串列佇列的結點,連結串列佇列中所有結點的資料型別應該是相同的
typedef struct QueueLikedList
{
DataType_t data; // 結點的資料域
struct QueueLikedList *next; // 結點的指標域
} QueueLList_t;
構造連結串列佇列管理結點,記錄佇列的隊首及隊尾,單獨定義可節省空間
typedef struct QueueMnager
{
struct QueueLikedList *Front; // 管理體的隊首指標 指向的型別應該是連結串列佇列的結點
struct QueueLikedList *Rear; // 管理體的隊尾指標 指向的型別應該是連結串列佇列的結點
} QueueMnager_t;
建立單連結串列空佇列
/*******************************************************************
*
* 函式名稱: CirQueueLList_Create
* 函式功能: 建立單連結串列空佇列
* 函式引數: none
* 返回結果:
* @Head 空佇列的管理結構體地址
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/26
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
// 建立一個空連結串列佇列,空連結串列佇列應該有一個頭結點,對連結串列佇列進行初始化
QueueMnager_t *CirQueueLList_Create(void)
{
// 1.建立一個頭結點並對頭結點申請記憶體
QueueMnager_t *Head = (QueueMnager_t *)calloc(1, sizeof(QueueMnager_t));
if (NULL == Head)
{
perror("Calloc memory for Head is Failed");
exit(-1);
}
// 2.對頭結點進行初始化
Head->Front = NULL; // 隊首指標指向NULL
Head->Rear = NULL; // 隊尾指標指向NULL
// 3.把頭結點的地址返回即可
return Head;
}
建立單連結串列新結點
/*******************************************************************
*
* 函式名稱: QueueLList_NewNode
* 函式功能: 建立單連結串列新結點
* 函式引數:
* @data 新結點資料域的資料
* 返回結果:
* @New 新結點的地址
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/26
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
// 建立新的結點,並對新結點進行初始化(資料域 + 指標域)
QueueLList_t *QueueLList_NewNode(DataType_t data)
{
// 1.建立一個新結點並對新結點申請記憶體
QueueLList_t *New = (QueueLList_t *)calloc(1, sizeof(QueueLList_t));
if (NULL == New)
{
perror("Calloc memory for NewNode is Failed");
return NULL;
}
// 2.對新結點的資料域和指標域進行初始化
New->data = data;
New->next = NULL;
return New;
}
判斷佇列是否為空
/*******************************************************************
*
* 函式名稱: QueueLList_IsEmpty
* 函式功能: 判斷佇列是否為空
* 函式引數:
* @Head 佇列管理結構體的地址
* 返回結果:
* @bool 為空返回ture,非空返回false
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/26
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
// 判斷連結串列佇列是否為空
bool QueueLList_IsEmpty(QueueMnager_t *Head)
{
// 當管理結構體中的隊首隊尾指標都指向NULL時 表示佇列中沒有結點
return (NULL == Head->Front && NULL == Head->Rear) ? true : false;
}
入隊 向連結串列佇列的尾部進行插入操作
/*******************************************************************
*
* 函式名稱: QueueLList_Enqueue
* 函式功能: 入隊 向連結串列佇列的尾部進行插入操作
* 函式引數:
* @Head 佇列管理結構體的地址
* @data 入隊結點資料域的值
* 返回結果:
* @Head 返回入隊操作後管理結構體的地址
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/26
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
// 入隊 向連結串列佇列的尾部進行插入操作
QueueMnager_t *QueueLList_Enqueue(QueueMnager_t *Head, DataType_t data)
{
// 建立新結點接收入隊資料
QueueLList_t *New = QueueLList_NewNode(data);
// 判斷佇列是否為空 為空時佇列的隊首隊尾應當都指向新結點
if (QueueLList_IsEmpty(Head))
{
Head->Front = New;
Head->Rear = New;
}
else
{
Head->Rear->next = New; // 佇列非空時 隊尾指標指向的結點中的next指標應指向新結點
Head->Rear = New; // 隊尾指標應指向新結點
}
return Head;
}
出隊
向連結串列佇列的頭部進行刪除操作
將出隊結點資料域的資料儲存到變數val中,通常出隊操作時涉及到資料輸出,所以需要傳入主函式的變數地址,防止出隊資料在函式呼叫結束後丟失
/*******************************************************************
*
* 函式名稱: QueueLList_Dequeue
* 函式功能: 出隊 對連結串列佇列的頭部進行刪除操作
* 函式引數:
* @Head 佇列管理結構體的地址
* @val 出隊資料存入的地址
* 返回結果:
* @bool 返回出隊是否成功
* 注意事項: None
* 函式作者: mailLinL@163.com
* 建立日期: 2024/04/26
* 修改歷史:
* 函式版本: V1.0
* *****************************************************************/
// 出隊 對連結串列佇列的頭部進行刪除操作 將出隊結點資料域的資料儲存到變數val中
bool QueueLList_Dequeue(QueueMnager_t *Head, DataType_t *val)
{
if (QueueLList_IsEmpty(Head))
{
printf("Queue Linked List is Empty!");
return false;
}
else
{
QueueLList_t *temp = Head->Front; // 定義指標記錄原隊首的地址
*val = Head->Front->data; // 將原隊首資料域中的值存入變數val中
Head->Front = Head->Front->next; // 將隊首指標指向隊首的下一個結點
temp->next = NULL; // 將原隊首中的next指標指向NULL
free(temp); // 釋放原隊首結點的記憶體
}
return true;
}
主函式中測試
int main(int argc, char const *argv[])
{
// 建立一個新佇列
QueueMnager_t *Queue = CirQueueLList_Create();
// 資料入隊10 15 20
QueueLList_Enqueue(Queue, 10);
QueueLList_Enqueue(Queue, 15);
QueueLList_Enqueue(Queue, 20);
DataType_t temp;
// 出隊10 15 20
QueueLList_Dequeue(Queue, &temp);
printf("%d\n", temp);
QueueLList_Dequeue(Queue, &temp);
printf("%d\n", temp);
QueueLList_Dequeue(Queue, &temp);
printf("%d\n", temp);
return 0;
}
測試結果
總結
佇列遵循“先進先出”的規則,在實際程式設計中可以用多種方法實現,如順序表,棧,單連結串列,雙連結串列等等,這些資料結構可能有多種資料輸入及輸出的方式,所以在構造佇列時,一定要注意佇列的規則