前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【数据结构】队列篇

【数据结构】队列篇

作者头像
Yui_
发布2024-10-16 08:21:40
550
发布2024-10-16 08:21:40
举报
文章被收录于专栏:Yui编程知识

1.队列

1.1 队列的概念及结构

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾。 出队列:进行删除操作的一端称尾队头。

队列图
队列图

2. 队列的实现

队列和栈一样,既可以用数组来实现也可以用链表来实现,不过因为队列不仅会用到队尾还会用到队头的特性,用链表来实现更优一些,用数组会降低效率。 入队演示

入队演示
入队演示

出队演示

出队演示
出队演示

2.1 准备工作

创建两个结构体,一个结构体用来维护队列的节点,一个结构体用来维护队列的首尾。 还可以在queue中再维护一个size,用来记录链表的节点数量。当然这里我没有这样写

代码语言:javascript
复制
#define Datatype int
//节点,维持队列的节点
typedef struct Node
{
	Datatype data;
	struct Node* next;
}Node;

//队列,维护队列的头和尾
typedef struct Queue
{
	Node* front;
	Node* tail;
}Queue;

2.2 队列的初始化

因为初始时是没有节点的,把队列的首尾都初始化尾NULL

代码语言:javascript
复制
//初始化
void InitQueue(Queue* pq)
{
	assert(pq);
	pq->front = NULL;
	pq->tail = NULL;
}

2.3 队尾入队列

创建节点后开始判断,如果当前节点为空,那么我们就把队列的头和尾都指向这个新创建的节点。 如果队列已经有节点了,那么我们就把它链接的队尾的next,然后再更新队尾指针。

代码语言:javascript
复制
//队尾入队列
void PushQueue(Queue* pq, Datatype x)
{
	assert(pq);
	//创建节点
	Node* newnode = (Node*)malloc(sizeof(Node));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)//如果队列为空
	{
		//此时队头和队为指向同一节点
		pq->front = newnode;
		pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		//更新队尾指针
		pq->tail = newnode;
	}
}

2.4 队头出队列

出队列就是要删除嘛,不能是空的,为此我们加一个断言就好了。 删除队列节点时,因为是队首节点,删它前我们先要找到队首节点的下一个节点以防链表丢失,然后更新队首指针。 注意:如果队列就只有一个节点,再删除后要感谢队首和队尾指针。 。

代码语言:javascript
复制
//队头出队列
void PopQueue(Queue* pq)
{
	assert(pq);
	assert(pq->front);//防止队列为空
	if (pq->front == pq->tail)
	{
		free(pq->front);
		pq->front = pq->tail = NULL;
		return;
	}
	Node* cur = pq->front->next;
	free(pq->front);
	pq->front = cur;
}

2.5 获取队列头部元素

因为队首指针存在,直接返回队首指针指向节点的值。

代码语言:javascript
复制
//获取队列头部元素
Datatype FrontQueue(Queue* pq)
{
	assert(pq);
	assert(pq->front);
	return pq->front->data;
}

2.6 获取队列队尾元素

因为队尾指针存在,直接返回队尾指针指向节点的值。

代码语言:javascript
复制
//获取队列队尾元素
Datatype BackQueue(Queue* pq)
{
	assert(pq);
	assert(pq->tail);
	return pq->tail->data;
}

2.7 获取队列有效元素个数

因为在准备阶段我们并没有用队列维护一个size,所以这里要遍历队列来求有效元素的个数。

代码语言:javascript
复制
//获取队列有效元素个数
int SizeQueue(Queue* pq)
{
	assert(pq);
	int sz = 0;
	Node* cur = pq->front;
	while (cur)
	{
		sz += 1;
		cur = cur->next;
	}
	return sz;
}

2.8 检测队列是否为空

检测队列是否为空,如果为空返回真,否则返回假,注意别搞反了

代码语言:javascript
复制
//检测队列是否为空,如果为空返回真,否则返回假
bool EmptyQueue(Queue* pq)
{
	assert(pq);
	return pq->front == NULL;
}

2.9 销毁队列

使用了动态内存一定要记得销毁,不然会有内存泄漏的~

代码语言:javascript
复制
//销毁队列
void DestoryQueue(Queue* pq)
{
	assert(pq);
	Node* cur = pq->front;
	while (cur)
	{
		Node* next = cur->next;
		free(cur);
		cur = NULL;
		cur = next;
	}
}

3. 代码整合

代码语言:javascript
复制
//queue.h
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>

#define Datatype int
//节点,维持队列的节点
typedef struct Node
{
	Datatype data;
	struct Node* next;
}Node;

//队列,维护队列的头和尾
typedef struct Queue
{
	Node* front;
	Node* tail;
}Queue;

//初始化
void InitQueue(Queue* pq);

//队尾入队列
void PushQueue(Queue* pq, Datatype x);

//队头出队列
void PopQueue(Queue* pq);

//获取队列头部元素
Datatype FrontQueue(Queue* pq);

//获取队列队尾元素
Datatype BackQueue(Queue* pq);

//获取队列有效元素个数
int SizeQueue(Queue* pq);

//检测队列是否为空,如果为空返回真,否则返回假
bool EmptyQueue(Queue* pq);

//销毁队列
void DestoryQueue(Queue* pq);

//queue.c
#include "queue.h"

//初始化
void InitQueue(Queue* pq)
{
	assert(pq);
	pq->front = NULL;
	pq->tail = NULL;
}

//队尾入队列
void PushQueue(Queue* pq, Datatype x)
{
	assert(pq);
	//创建节点
	Node* newnode = (Node*)malloc(sizeof(Node));
	if (newnode == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	newnode->data = x;
	newnode->next = NULL;
	if (pq->tail == NULL)//如果队列为空
	{
		//此时队头和队为指向同一节点
		pq->front = newnode;
		pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

//队头出队列
void PopQueue(Queue* pq)
{
	assert(pq);
	assert(pq->front);
	if (pq->front == pq->tail)
	{
		free(pq->front);
		pq->front = pq->tail = NULL;
		return;
	}
	Node* cur = pq->front->next;
	free(pq->front);
	pq->front = cur;
}

//获取队列头部元素
Datatype FrontQueue(Queue* pq)
{
	assert(pq);
	assert(pq->front);
	return pq->front->data;
}

//获取队列队尾元素
Datatype BackQueue(Queue* pq)
{
	assert(pq);
	assert(pq->tail);
	return pq->tail->data;
}

//获取队列有效元素个数
int SizeQueue(Queue* pq)
{
	assert(pq);
	int sz = 0;
	Node* cur = pq->front;
	while (cur)
	{
		sz += 1;
		cur = cur->next;
	}
	return sz;
}

//检测队列是否为空,如果为空返回真,否则返回假
bool EmptyQueue(Queue* pq)
{
	assert(pq);
	return pq->front == NULL;
}

//销毁队列
void DestoryQueue(Queue* pq)
{
	assert(pq);
	Node* cur = pq->front;
	while (cur)
	{
		Node* next = cur->next;
		free(cur);
		cur = NULL;
		cur = next;
	}
}

//test.c
#include "queue.h"

void test1()
{
	//Queue q;
	//InitQueue(&q);
	//PushQueue(&q,1);
	//PushQueue(&q,2);
	//PushQueue(&q,3);
	//PushQueue(&q,4);

	//printf("%d\n", SizeQueue(&q));
	//printf("%d\n", BackQueue(&q));
	//printf("%d\n", FrontQueue(&q));
	//DestoryQueue(&q);
}
int main()
{
	test1();
	return 0;
}

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.队列
    • 1.1 队列的概念及结构
    • 2. 队列的实现
      • 2.1 准备工作
        • 2.2 队列的初始化
          • 2.3 队尾入队列
            • 2.4 队头出队列
              • 2.5 获取队列头部元素
                • 2.6 获取队列队尾元素
                  • 2.7 获取队列有效元素个数
                    • 2.8 检测队列是否为空
                      • 2.9 销毁队列
                      • 3. 代码整合
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档