『初阶数据结构 • C语言』⑩ - 队列的概念与实现(附完整源码)


 

 

1.队列的概念及结构

队列对于临时数据的处理也十分有趣,它跟栈一样都是有约束条件的数组(或者链表)。区别在于我们想要按什么顺序去处理数据,而这个顺序当然是要取决于具体的应用场景。

你可以将队列想象成是电影院排队。排在最前面的人会最先离队进入影院。套用到队列上,就是首先加入队列的,将会首先从队列移出。

因此计算机科学家都用缩写“FIFO”(first in, first out)先进先出,来形容它。

与栈类似,队列也有 3个限制(但内容不同)。

  ▶ 只能在末尾插入数据(这跟栈一样)。
  ▶ 只能读取开头的数据(这跟栈相反)。
  ▶ 只能移除开头的数据(这也跟栈相反)。

下面来看看它是怎么运作的,先准备一个空队列。

首先,插入 5(虽然栈的插入就叫压栈,但队列的插入却没有固定的叫法,一般可以叫放入、
加入、入队)。

然后,插入 9。 

接着,插入 100。 

目前为止,队列表现得还跟栈一样,但要是移除数据的话,就会跟栈反着来了,因为队列是从开头移除数据的。

想移除数据,得先从 5 开始,因为开头就是它。 

接着,移除 9。 

这样一来,队列就只剩下 100了。 

2.队列的实现

队列也可以数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。

2.1队列结构的定义

typedef struct Queue
{
	QNode* head; //记录队头的位置
	QNode* tail; //记录队尾的位置
	int size; //记录队列的长度
}Queue;

2.2队列中存储数据的结点

typedef int QDataType;

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

2.3函数接口的实现

首先是在Queue.h文件中进行函数声明

Queu.h

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

typedef int QDataType;

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

typedef struct Queue
{
	QNode* head; //记录队头的位置
	QNode* tail; //记录队尾的位置
	int size; //记录队列的长度
}Queue;

//队列的初始化
void QueueInit(Queue* pq);
//释放malloc出的内存
void QueueDestroy(Queue* pq);
//入队
void QueuePush(Queue* pq, QDataType x);
//出队
void QueuePop(Queue* pq);
//获取队头的数据
QDataType QueueFront(Queue* pq);
//获取队尾的数据
QDataType QueueBack(Queue* pq);
//判断队列是否为空
bool QueueEmpty(Queue* pq);
//队列数据的个数
int QueueSize(Queue* pq);

在Queue.c文件中进行函数的定义

Queue.c

#define _CRT_SECURE_NO_DEPRECATE 1
#include"Queue.h"

void QueueInit(Queue* pq)
{
	assert(pq);

	pq->head = NULL;
	pq->tail = NULL;
	pq->size = 0;
}

void QueueDestroy(Queue* pq)
{
	assert(pq);
	//用cur找尾
	QNode* cur = pq->head;
	while (cur)
	{
		QNode* del = cur;
		cur = cur->next;

		free(del);
	}
	pq->size = 0;
	pq->head = pq->tail = NULL;
}

void QueuePush(Queue* pq,QDataType data)
{
	assert(pq);

	QNode* newNode = (QNode*)malloc(sizeof(QNode));
	if (newNode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	//初始化结点
	newNode->data = data;
	newNode->next = NULL;

	if (pq->tail == NULL)
	{
		//队列为空时入队
		pq->head = newNode;
		pq->tail = newNode;
	}
	else
	{
		//队列不为空时入队
		pq->tail->next = newNode;
		pq->tail = newNode;
	}
	
	pq->size++;
}

void QueuePop(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	if (pq->head->next == NULL)
	{
		//只有一个结点时
		free(pq->head);
		pq->head = pq->tail = NULL;
	}
	else
	{
		//一般情况
		QNode* del = pq->head;
		pq->head = pq->head->next;

		free(del);
	}
	pq->size--;
}

QDataType QueueFront(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->head->data;
}

QDataType QueueBack(Queue* pq)
{
	assert(pq);
	assert(!QueueEmpty(pq));

	return pq->tail->data;
}

bool QueueEmpty(Queue* pq)
{
	assert(pq);

	//return pq->size==0;
	return pq->head == NULL && pq->tail == NULL;
}

int QueueSize(Queue* pq)
{
	assert(pq);

	return pq->size;
}

 

 

  • 68
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 74
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 74
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花想云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值