数据结构——队列

本文介绍了如何使用链表实现一个基本的队列数据结构,包括队列的概念、初始化、销毁、入队、出队、判空、获取元素个数以及头部和尾部元素的方法。提供的C代码详细展示了这些功能的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一、队列的概念

二、队列的实现 

1. 创建队列

2. 队列初始化

3. 销毁队列

4. 入队

5. 出队

6. 判空

7. 获取队列元素个数

8. 获取队列头部

9. 获取队列尾部元素

三、总代码

Queue.h 

Queue.c

Test.c


一、队列的概念

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

采用链表实现队列比较方便,出队就类似于头删,入队就为尾插。

二、队列的实现 

1. 创建队列

需要定义两个结构体,一个用来定义节点,一个用来定义队列,即队头队尾等信息。


//创建队列结构
typedef int QDataType; 

//一个节点
typedef struct QueueNode 
{
	QDataType data; //存储数据
	struct QueueNode* next; //记录下一个节点
}QNode;

//保存队头和队尾
typedef struct Queue
{
	QNode* head; //头指针
	QNode* tail; //尾指针
}Queue;

2. 队列初始化

队列可以为空,但是指向头指针和尾指针的结构体不能为空,所以一开始就要断言。其次,在插入数据前,队列肯定是空的,所以直接把头指针和尾指针置空即可。

//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);//传入的队列地址不能为空
	pq->head = pq->tail = NULL;
}

3. 销毁队列

销毁队列就是把队列的每个数据都销毁掉,那么需要遍历链表进行挨个销毁free。首先定义一个cur指针指向pq->head,用来保存第一个数据,遍历cur,如果不为空,就free。最后把tail和head置空即可。

//销毁队列
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;
}

4. 入队

 入队就类似于链表尾插,首先创建一个新节点newnode,初始化节点。下来分为队列为空和有数据。若对垒为空,则将head和tail节点指向新节点newnode即可。有数据则需要将tail的next指向新节点newnode,然后令newnode为tail新的尾部即可。

//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));//创建一个新节点
	assert(newnode);
	newnode->next = NULL;
	newnode->data = x;

	if (pq->tail == NULL)//空队列则两其头尾均指向新节点
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

5. 出队

出队就类似于链表的头删,分两种情况,一种是当队列仅剩一个数据时,此时head=tail,若删除head,则tail变为野指针了,此中情况需要单独讨论,分别置空head和tail即可。

一般情况,为定义一个next指针保存头节点的下一个节点,再删除head,令next为新的head。

//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head && pq->tail);//头尾均不能为空
	if (pq->head->next == NULL)//当只有一个节点时
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

6. 判空

判断队列为空,则head和tail均为空时候。

//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

7. 获取队列元素个数

遍历队列,定义指针从头开始遍历,个数++,指向空时停止。

再队列结构中定义一个size专门用来保存节点个数。

下面为遍历获取队列元素个数:

//获取有效元素个数
size_t QueueSize(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	size_t size = 0;
	while (cur)
	{
		size++;
		cur = cur->next;
	}
	return size;
}

8. 获取队列头部

当队列不为空时候,直接返回队列头部元素即可。

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head); //头部不能为空
	return pq->head->data;
}

9. 获取队列尾部元素

//获取队尾元素
QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(pq->tail); //尾部不能为空
	return pq->tail->data;
}

三、总代码

Queue.h 

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

//创建队列结构
typedef int QDataType; 

//一个节点
typedef struct QueueNode 
{
	QDataType data; //存储数据
	struct QueueNode* next; //记录下一个节点
}QNode;

//保存队头和队尾
typedef struct Queue
{
	QNode* head; //头指针
	QNode* tail; //尾指针
}Queue;

//初始化队列
void QueueInit(Queue* pq);

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

//入队
void QueuePush(Queue* pq, QDataType x);

//出队
void QueuePop(Queue* pq);

//判空
bool QueueEmpty(Queue* pq);

//获取有效元素个数
size_t QueueSize(Queue* pq);

//获取队头元素
QDataType QueueFront(Queue* pq);

//获取队尾元素
QDataType QueueBack(Queue* pq);

Queue.c

#include"Queue.h"



//初始化队列
void QueueInit(Queue* pq)
{
	assert(pq);
	pq->head = pq->tail = NULL;
}

//销毁队列
void QueueDestory(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* next = cur->next;
		free(cur);
		cur = next;
	}
	pq->head = pq->tail = NULL;//指针置空
}

//入队
void QueuePush(Queue* pq, QDataType x)
{
	assert(pq);
	QNode* newnode = (QNode*)malloc(sizeof(QNode));//创建一个新节点
	assert(newnode);
	newnode->next = NULL;
	newnode->data = x;

	if (pq->tail == NULL)//空队列则两其头尾均指向新节点
	{
		assert(pq->head == NULL);
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}
}

//出队
void QueuePop(Queue* pq)
{
	assert(pq);
	assert(pq->head && pq->tail);//头尾均不能为空
	if (pq->head->next == NULL)//当只有一个节点时
	{
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		QNode* next = pq->head->next;
		free(pq->head);
		pq->head = next;
	}
}

//判空
bool QueueEmpty(Queue* pq)
{
	assert(pq);
	return pq->head == NULL;
}

//获取有效元素个数
size_t QueueSize(Queue* pq)
{
	assert(pq);
	QNode* cur = pq->head;
	size_t size = 0;
	while (cur)
	{
		size++;
		cur = cur->next;
	}
	return size;
}

//获取队头元素
QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(pq->head);//头不能为空才可以获取头部数据
	return pq->head->data;
}

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

Test.c

#include"Queue.h"
void TestQueue()
{
	Queue q;
	QueueInit(&q);
	//插入数据
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	
	//打印
	while (!QueueEmpty(&q))
	{
		printf("%d ", QueueFront(&q));
		QueuePop(&q);
	}
	printf("\n");
}

int main()
{
	TestQueue();
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值