队列_单向链表
利用单向链表设计一个队列,实现“先进先出”的功能
队列的两端都允许操作,只不过要求数据只能从队列的一端插入,从队列的另一端删除,可以把队列理解为一根水管,水管有进水口和出水口。
一般把允许数据插入的一端称为队尾(Tail或者Rear),一般把允许删除数据的一端称为队头队首(Head或者Front)。
- 把允许数据插入的一端称为队尾(允许数据插入到队列的操作称为入队,英文enqueue)
- 把允许删除数据的一端称为队头(允许数据从队列删除的操作称为出队,英文dequeue)
程序结构思路:
.将单向链表的首结点当作堆首,尾结点当作队尾,入队相当于尾插操作,出队相当于头删操作。
程序:
/********************************************************************************************
* file name: Queue_LList.c
* author : liaojx2016@126.com
* date : 2024/04/26
* function : Design a queue to achieve “first input first output”
* note : None
*
* CopyRight (c) 2023-2024 liaojx2016@126.com All Right Reseverd
*
*********************************************************************************************/
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<stdlib.h>
typedef int DataType_t;
typedef struct QueueLList
{
DataType_t data; //结点的数据域
struct QueueLList *next; //结点的指针域
}QueueLList_t;
/**********************************************************************************************
* func name : QueueLList_Create
* function : Create a empty stack link list
* func parameter : None
* return resuolt : Address of head node
* author : liaojx2016@126.com
* date : 2024/04/26
* note : None
* modify history : None
* function section: v1.0
*
**********************************************************************************************/
//创建一个空链表,空链表应该有一个头结点,对链表进行初始化
QueueLList_t * QueueLList_Create(void)
{
//1.创建一个头结点并对头结点申请内存
QueueLList_t *Head = (QueueLList_t *)calloc(1,sizeof(QueueLList_t));
//判断是否内存申请成功
if (NULL == Head) {
perror("Calloc memory for Head is Failed");
exit(-1);
}
//2.对头结点进行初始化,头结点是不存储有效内容的!!!
Head->next = NULL;
//3.把头结点的地址返回即可
return Head;
}
/**********************************************************************************************
* func name : QueueLList_NewNode
* function : Create a new node and do initialization
* func parameter :
* @data :address of head node
* return resuolt : Address of a new node
* author : liaojx2016@126.com
* date : 2024/04/26
* note : None
* modify history : None
* function section: 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;
}
/**********************************************************************************************
* func name : Enqueue
* function : Enqueue a data
* func parameter :
* @data :Enqueue data
* @Head :Address of head node
* return resuolt : Enqueue success result (true or false)
* author : liaojx2016@126.com
* date : 2024/04/26
* note : None
* modify history : None
* function section: v1.0
*
**********************************************************************************************/
bool Enqueue(QueueLList_t *Head,DataType_t data)
{
//1.创建新的结点,并对新结点进行初始化
QueueLList_t *New = QueueLList_NewNode(data);
if (NULL == New)
{
printf("can not insert new node\n");
return false;
}
//printf("New->data=%d\n",New->data);
//2.判断链表是否为空,如果为空,则直接插入即可
if (NULL == Head->next)
{
Head->next = New;
return true;
}
//3.如果链表为非空,则把新结点插入到链表的尾部
QueueLList_t *p = Head->next;
//遍历链表,p指针到达尾结点
while(p->next != NULL) {
p = p->next;
}
//将新结点插入尾节点之后
p->next = New;
return true;
}
/**********************************************************************************************
* func name : Dequeue
* function : Dequeue a data and output
* func parameter :
* @Head :address of head node
* return resuolt : Dequeue success result (true or false)
* author : liaojx2016@126.com
* date : 2024/04/26
* note : None
* modify history : None
* function section: v1.0
*
**********************************************************************************************/
bool Dequeue(QueueLList_t *Head)
{
//当链表为空,删除失败,返回false
if (NULL == Head->next)
{
//printf("Stack linklist is empty\n");
return false;
}
QueueLList_t *p = Head->next; //备份首结点
printf("the dequeue element is %d\n",Head->next->data);
//首部删除一个结点
Head->next = Head->next->next; //头结点的next指针指向首结点的直接后继
p->next = NULL; //将原首结点的next指针指向NULL
free(p); //释放原首结点
return true;
}
/**********************************************************************************************
* func name : QueueLList_Print
* function : Queue data print
* func parameter :
* @Head :address of head node
* return resuolt : Print success result (true or false)
* author : liaojx2016@126.com
* date : 2024/04/25
* note : None
* modify history : None
* function section: v1.0
*
**********************************************************************************************/
//遍历
bool QueueLList_Print(QueueLList_t *Head)
{
if (Head->next == NULL) {
printf("stack link list is empty\n");
return false;
}
//对链表的头文件的地址进行备份
QueueLList_t *Phead = Head;
printf("the Stack linkedlist data is \n");
//遍历结点,输出数据
do
{
//把头的直接后继作为新的头结点
Phead = Phead->next;
//输出头结点的直接后继的数据域
printf("%d ",Phead->data);
}
while( Phead->next );
printf("\n");
return true;
}
int main(int argc, char const *argv[])
{
//定义一个头指针
QueueLList_t *head = QueueLList_Create();
//Enqueue 入队,Dequeue 出队并输出数据,QueueLList_Print 遍历以便测试打印
Enqueue(head,3);
Dequeue(head);
QueueLList_Print(head);
Enqueue(head,7);
Enqueue(head,4);
Enqueue(head,2);
QueueLList_Print(head);
Dequeue(head);
QueueLList_Print(head);
return 0;
}
测试输出结果