代码:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
队列--双向循环链表实现
通过对线性表的插入删除操作在异端完成
比如:
头插入对应的是尾删除
尾插入对应的是头删除
出数据的一端是队头,进数据的是队尾
栈: 先进后出
队列: 先进先出
*/
// 创建双向循环链表节点
struct Node
{
int a;
struct Node* pPre;
struct Node* pNext;
};
// 1.创建队列的空头
struct Node* Queue();
// 2.判断队列是否为空
bool isEmpty(struct Node* pQueue);
// 3.获取队头 -- 出数据的一端
struct Node* Front(struct Node* pQueue);
// 4.获取队尾 -- 进数据的一端
struct Node* Back(struct Node* pQueue);
// 5.入队
void Push(struct Node* pQueue, int a);
// 6.出队
void PopEnd(struct Node* pQueue);
// 7.释放队列
void Free(struct Node** pQueue);
int main()
{
// 创建队列空头
struct Node* pHead = Queue();
// 判断队列是否为空
bool ret = isEmpty(pHead); // true
int arr[5] = { 1,2,3,4,5 };
// 入队
for (int i = 0; i < 5; i++)
{
Push(pHead, arr[i]); // 5 4 3 2 1 【头添加】
}
// 获取队头
for (int i = 0; i < 5; i++)
{
// 获取队头
arr[i] = Front(pHead)->a;
printf("%d\t", arr[i]); // 5 4 3 2 1
// 出队
PopEnd(pHead);
}
system("pause");
return 0;
}
// 1.创建队列的空头
struct Node* Queue()
{
// 创建节点,动态申请内存空间
struct Node* pt = (struct Node*)malloc(sizeof(struct Node));
// 判空
if (NULL == pt)
{
return NULL;
}
// 给节点成员赋值
pt->a = -1;
// 注意这里前后指针要指向自身,形成一个环
pt->pNext = pt;
pt->pPre = pt;
return pt;
}
// 2.判断队列是否为空
bool isEmpty(struct Node* pQueue)
{
if (NULL == pQueue || pQueue == pQueue->pNext)
{
return true;
}
return false;
}
// 3.获取队头 -- 出数据的一端 获取尾节点
//【这里用:头添加 尾删除,出数据的一端是队头,进数据的一端是队尾】
struct Node* Front(struct Node* pQueue)
{
// 判断链表是否为空
if (NULL == pQueue || pQueue->pNext == pQueue)
{
return NULL;
}
// 返回尾节点
return pQueue->pPre;
}
// 4.获取队尾 -- 进数据的一端 获取头节点(空头的下一个节点)
struct Node* Back(struct Node* pQueue)
{
// 判断队列是否为空
if (NULL == pQueue || pQueue->pNext == pQueue)
{
return NULL;
}
// 返回空头的下一个节点 队列第二个节点
return pQueue->pNext;
}
// 5.入队
void Push(struct Node* pQueue, int a)
{
// 检验参数合法性
if(NULL == pQueue)
{
return;
}
// 进行头添加
// 创建要插入的节点
struct Node* pt = (struct Node*)malloc(sizeof(struct Node));
// 判空
if (NULL == pt)
{
return;
}
// 给节点赋值
pt->a = a;
pt->pNext = NULL;
pt->pPre = NULL;
// 将节点插入到头
// 先连
pt->pPre = pQueue->pPre;
pt->pNext = pQueue;
// 后断
pQueue->pPre->pNext = pt;
pQueue->pPre = pt;
}
// 6.出队 -- 尾删除
void PopEnd(struct Node* pQueue)
{
// 检验参数合法性
if (NULL == pQueue)
{
return;
}
// 记录要删除的尾节点
struct Node* pt = pQueue->pPre;
// 抠出尾
pt->pPre->pNext = pQueue;
pQueue->pPre = pt->pPre;
// 释放记录的尾节点
free(pt);
}
// 7.释放队列
void Free(struct Node** pQueue)
{
// 检验参数合法性
if (NULL == *pQueue)
{
return;
}
// 记录空头
struct Node* pt = *pQueue;
do
{
// 记录要释放的pt
struct Node* pTemp = pt;
// 抠出pt
pt = pt->pNext;
// 释放抠出的pt
free(pTemp);
// 将记录的pt 置空
pTemp = NULL;
} while (pt != *pQueue);
// 将空队头置空
*pQueue = NULL;
}
程序运行结果: