自定義單連結串列佇列的基本介面函式(非迴圈佇列)

林大官人995發表於2024-04-26

單連結串列構建佇列的介面函式

/*******************************************************************
*

  • 檔名稱 : 單連結串列構建佇列的介面函式
  • 檔案作者 : 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;
}

測試結果

image

總結

佇列遵循“先進先出”的規則,在實際程式設計中可以用多種方法實現,如順序表,棧,單連結串列,雙連結串列等等,這些資料結構可能有多種資料輸入及輸出的方式,所以在構造佇列時,一定要注意佇列的規則

相關文章