目录
1.队列
1.1队列的概念及结构
1.2队列的实现
1.3接口以及实现
Queue.h
Queue.c
申请一个队列的节点
初始化队列
入队列
出队列
查找队头元素
查找队尾元素
获取队列长度
判断是否为空队列
队列的销毁
测试用例
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头,形象一点就是吃进去拉出来
可以用顺序结构来实现,也可以用链式结构实现,但是顺序结构要搬运元素 ,头插尾删就比较耗时间,所以采用链式结构来实现,一个带头借点的单链表。
#pragma once
#include
#include
#include
#include
typedef int Datatype;
typedef struct Queuenode{
struct Queuenode* next;
Datatype data;
}Queuenode;
typedef struct Queue {
Queuenode* front;
Queuenode* back;
}Queue;
//申请一个队列的节点
Queuenode* CreateQueueNode(Datatype data);
//初始化队列
void QueueInit(Queue* p);
//入队列
void QueuePush(Queue* p, Datatype data);
//出队列
void QueuePop(Queue* p);
//查找队头元素
Datatype QueueFront(Queue* p);
//查找队尾元素
Datatype QueueBack(Queue* p);
//获取队列长度
int QueueSize(Queue* p);
//判断是否为空队列
int QueueEmpty(Queue* p);
//队列的销毁
void QueueDestory(Queue* p);
#include "Queue.h"
//申请一个队列的节点
//相当一个带头结点的单链表
Queuenode* CreateQueueNode(Datatype data)
{
//直接malloc一个
Queuenode* Newnode = (Queuenode*)malloc(sizeof(Queuenode));
//查看是否申请成功
if (NULL == Newnode) {
assert(0);
return NULL;
}
//更新节点数据
Newnode->data = data;
Newnode->next = NULL;
return Newnode;
}
//初始化队列
void QueueInit(Queue* p)
{
//参数传入的判断
assert(p);
//给一个头结点
p->front = CreateQueueNode(0);
p->back = p->front;
}
//入队列
//其实就是带头单链表的尾插
void QueuePush(Queue* p, Datatype data)
{
//传入参数的合法性判断
assert(p);
//申请一个节点把传入数据放进去
Queuenode* Newnode = CreateQueueNode(data);
//直接尾插,next指针指向这个新节点,把他连接起来
p->back->next = Newnode;
p->back = Newnode;
}
//出队列
//其实就是带头单链表的头删
void QueuePop(Queue* p)
{
Queuenode* Delnode = NULL;
//先判断是否为空
if (QueueEmpty(p)) {
return;
}
//标记删除节点,头删
Delnode = p->front->next;
//然后在连接起来
p->front->next = Delnode->next;
//队列中刚好只有一个元素,删除之后应该要将队尾back放在头节点的位置
if (Delnode == p->back) {
p->back = p->front;
}
free(Delnode);
}
//查找队头元素
Datatype QueueFront(Queue* p)
{
//对传入参数合法性的判断
assert(p);
return p->front->next->data;
}
//查找队尾元素
Datatype QueueBack(Queue* p)
{
//对传入参数合法性的判断
assert(p);
return p->back->data;
}
//获取队列长度
int QueueSize(Queue* p)
{
//对传入参数合法性的判断
assert(p);
//哎呦 这不是我的老朋友计数器吗
int count = 0;
//好家伙 这不是老伙计遍历指针
Queuenode* cur = p->front->next;
while (cur) {
count++;
cur = cur->next;
}
return count;
}
//判断是否为空队列
int QueueEmpty(Queue* p)
{
//对传入参数合法性的判断
assert(p);
//俩指针都指向头结点这不就是空队列了
return p->front == p->back;
}
//队列的销毁
void QueueDestory(Queue* p)
{
//对传入参数合法性的判断
assert(p);
//先来一个便利指针
Queuenode* cur = p->front->next;
while (cur) {
//这个队头指针一个个指向下一个节点
p->front->next = cur->next;
free(cur);
cur = p->front->next;
}
free(p->front);
p->back = NULL;
p->front = NULL;
}
//测试用例
void text() {
Queue p;
QueueInit(&p);
printf("size = %d\n", QueueSize(&p));
printf("\n");
// 入队列
QueuePush(&p, 1);
QueuePush(&p, 2);
QueuePush(&p, 3);
QueuePush(&p, 4);
QueuePush(&p, 5);
QueuePush(&p, 6);
QueuePush(&p, 7);
printf("size = %d\n", QueueSize(&p));
printf("front = %d\n", QueueFront(&p));
printf("back = %d\n", QueueBack(&p));
printf("\n");
// 出队列
QueuePop(&p);
printf("size = %d\n", QueueSize(&p));
printf("front = %d\n", QueueFront(&p));
printf("back = %d\n", QueueBack(&p));
printf("\n");
QueuePop(&p);
QueuePop(&p);
QueuePop(&p);
QueuePop(&p);
QueuePop(&p);
printf("size = %d\n", QueueSize(&p));
printf("front = %d\n", QueueFront(&p));
printf("back = %d\n", QueueBack(&p));
printf("\n");
QueuePop(&p);
QueuePop(&p);
printf("size = %d\n", QueueSize(&p));
QueueDestory(&p);
}
int main() {
text();
}
//申请一个队列的节点
//相当一个带头结点的单链表
Queuenode* CreateQueueNode(Datatype data)
{
//直接malloc一个
Queuenode* Newnode = (Queuenode*)malloc(sizeof(Queuenode));
//查看是否申请成功
if (NULL == Newnode) {
assert(0);
return NULL;
}
//更新节点数据
Newnode->data = data;
Newnode->next = NULL;
return Newnode;
}
//初始化队列
void QueueInit(Queue* p)
{
//参数传入的判断
assert(p);
//给一个头结点
p->front = CreateQueueNode(0);
p->back = p->front;
}
//入队列
//其实就是带头单链表的尾插
void QueuePush(Queue* p, Datatype data)
{
//传入参数的合法性判断
assert(p);
//申请一个节点把传入数据放进去
Queuenode* Newnode = CreateQueueNode(data);
//直接尾插,next指针指向这个新节点,把他连接起来
p->back->next = Newnode;
p->back = Newnode;
}
//出队列
//其实就是带头单链表的头删
void QueuePop(Queue* p)
{
Queuenode* Delnode = NULL;
//先判断是否为空
if (QueueEmpty(p)) {
return;
}
//标记删除节点,头删
Delnode = p->front->next;
//然后在连接起来
p->front->next = Delnode->next;
//队列中刚好只有一个元素,删除之后应该要将队尾back放在头节点的位置
if (Delnode == p->back) {
p->back = p->front;
}
free(Delnode);
}
//查找队头元素
Datatype QueueFront(Queue* p)
{
//对传入参数合法性的判断
assert(p);
return p->front->next->data;
}
//查找队尾元素
Datatype QueueBack(Queue* p)
{
//对传入参数合法性的判断
assert(p);
return p->back->data;
}
//获取队列长度
int QueueSize(Queue* p)
{
//对传入参数合法性的判断
assert(p);
//哎呦 这不是我的老朋友计数器吗
int count = 0;
//好家伙 这不是老伙计遍历指针
Queuenode* cur = p->front->next;
while (cur) {
count++;
cur = cur->next;
}
return count;
}
//判断是否为空队列
int QueueEmpty(Queue* p)
{
//对传入参数合法性的判断
assert(p);
//俩指针都指向头结点这不就是空队列了
return p->front == p->back;
}
//队列的销毁
void QueueDestory(Queue* p)
{
//对传入参数合法性的判断
assert(p);
//先来一个便利指针
Queuenode* cur = p->front->next;
while (cur) {
//这个队头指针一个个指向下一个节点
p->front->next = cur->next;
free(cur);
cur = p->front->next;
}
free(p->front);
p->back = NULL;
p->front = NULL;
}
void text() {
Queue p;
QueueInit(&p);
printf("size = %d\n", QueueSize(&p));
printf("\n");
// 入队列
QueuePush(&p, 1);
QueuePush(&p, 2);
QueuePush(&p, 3);
QueuePush(&p, 4);
QueuePush(&p, 5);
QueuePush(&p, 6);
QueuePush(&p, 7);
printf("size = %d\n", QueueSize(&p));
printf("front = %d\n", QueueFront(&p));
printf("back = %d\n", QueueBack(&p));
printf("\n");
// 出队列
QueuePop(&p);
printf("size = %d\n", QueueSize(&p));
printf("front = %d\n", QueueFront(&p));
printf("back = %d\n", QueueBack(&p));
printf("\n");
QueuePop(&p);
QueuePop(&p);
QueuePop(&p);
QueuePop(&p);
QueuePop(&p);
printf("size = %d\n", QueueSize(&p));
printf("front = %d\n", QueueFront(&p));
printf("back = %d\n", QueueBack(&p));
printf("\n");
QueuePop(&p);
QueuePop(&p);
printf("size = %d\n", QueueSize(&p));
QueueDestory(&p);
}