数据结构之队列的实现

1.队列的概念及结构

1.队列:只允许在一端进行插入数据操作,在另一端进行删除数据的特殊线性表,队列具有先进先出FIFO(First In First Out)入队列:进行插入操作的另一端称为队尾出队列:进行删除操作的一段被称为队头
在这里插入图片描述
2.队列的结构:
因为我们用链表实现所以我们需要先构建一个节点的结构

Typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType val;
}Qnode;

不过我们这里还需要再定义一个结构体,因为我们需要队头出数据和队尾如数据,对于单链表来说,从后一个数据找到前一个数据是很困难的,所以我们这里定义两个指针,一个指针指向头节点,一个指针,指向尾节点,这样方便我们插入数据和删除数据。

Typedef struct Queue
{
	Qnode* phead;
	Qnode* ptail;
	int size
}

我们在这里定义了这个结构体不仅可以记录两个指针,还可以记录size为后面的操作带来便利,同时可以解决传二级指针的问题。

2.队列的实现

队列是可以使用数组的链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组上出数组效率较低,因为每次出一个数据,数组所有数据都需要向前挪动一位。

ok~,开始队列的实现:
头文件的代码如下

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

typedef int QDataType;

typedef struct QueueNode
{
	struct QueueNode* next;
	QDataType val;
}Qnode;

typedef struct Queue
{
	Qnode* phead;
	Qnode* ptail;
	int size;
}Queue;

// 初始化队列 
void QueueInit(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType data);
// 队头出队列 
void QueuePop(Queue* q);
// 获取队列头部元素 
QDataType QueueFront(Queue* q);
// 获取队列队尾元素 
QDataType QueueBack(Queue* q);
// 获取队列中有效元素个数 
int QueueSize(Queue* q);
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
bool QueueEmpty(Queue* q);
// 销毁队列 
void QueueDestroy(Queue* q);

接下来我们一一实现
首先就是我们的队列初始化

void QueueInit(Queue* q)
{
	assert(q);   //断言
	q->phead = NULL;  //置空
	q->ptail = NULL;
	q->size = 0;   
}

队尾入队列

void QueuePush(Queue* q, QDataType data)
{
	assert(q);           //断言
	Qnode* newnode = (Qnode*)malloc(sizeof(Qnode)); //创建节点
	if (newnode == NULL)
	{   //创建失败退出
		perror("malloc fail");
		exit(1);
	}
	newnode->next = NULL;   // 创建好了之后对新的节点初始化
	newnode->val = data;
    //插入队列时要分两种情况 1、队列中没有数据 2、队列中已经存在数据
	if (q->ptail==NULL)    
	{    //当没有数据时 头尾指针同时指向 新节点
		q->phead = q->ptail = newnode;
	}
	else
	{   //当有数据时将创建好的新节点跟原来的尾节点链接
		q->ptail->next = newnode;
		q->ptail = newnode;
	}
	q->size++;  //size++ 为后面做准备
}

队头出队列

void QueuePop(Queue* q)
{
	assert(q);   //断言一下
	assert(q->size != 0);  //既然我们要出数据所以我们这里的size不能为0,为0就是没有数据
	//出队列同样分为两种情况 1、队列中只剩下一个数据 2、队列中存在多个数据
	if (q->phead->next==NULL)
	{   //队列中只存在一个数据时,释放完空间后将指针置为空
		free(q->ptail);
		q->phead = q->ptail = NULL;
	}
	else
	{
	//有多个数据时,需要将原来指向头结点的指针记录下来,删除之后,指向队列新的头节点
		Qnode* cur = q->phead->next;
		free(q->phead);
		q->phead = cur;
	}
	q->size--;//每删除一个数据就size--
}

后面的就简单啦~
获取队列头部元素

QDataType QueueFront(Queue* q)
{
	assert(q);   //断言
	assert(q->phead);   //获取头元素所以phead指针不能为空
	return q->phead->val;   //得到不为空后,直接返回phead指向的值
}

获取队列尾部元素(和头部元素同理)

QDataType QueueBack(Queue* q)
{
	assert(q);
	assert(q->ptail);
	return q->ptail->val;
}

获取队列中有效地元素个数
这个时候我们刚刚记录的size的作用就来啦

int QueueSize(Queue* q)
{
	assert(q);
	return q->size; //直接返回size 即可
}

判断队列是否为空,为空返回true,反之返回false

bool QueueEmpty(Queue* q)
{
	assert(q);
	return q->size == 0;
}

队列的销毁

void QueueDestroy(Queue* q)
{
	assert(q);
	Qnode* cur = q->phead; //存下头节点
	while (cur)
	{
		Qnode* next = cur->next;  //一个个节点释放
		free(cur);
		cur = next;
	}
	q->phead = q->ptail = NULL;//最后置为空
	q->size = 0;
}

这样我们的队列实现 就大功告成啦~感谢观看,如果对C语言数据结构感兴趣,关注巨可爱熊一起学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值