【数据结构】【C语言】队列 动画详解

1 引子

  • 排队各位肯定都知道对吧,无非就是"叫一个走一个,叫一个走一个",我们在医院等号的时候,其实就是把你的号放进一个虚拟的队列里头,模拟排队,这就是队列

2 队列的定义

  • 队列是一个带有限制的线性表,他限制在你只能从尾部进入数据,再从头部出数据,就像排队一样,先进去的肯定先出来,后进去的肯定后出来(我么们来看看动画)

在这里插入图片描述

3 队列的实现

3.1 队列类型定义
  • 队列我们一般用链表实现,当然用顺序表其实也是可以的,只是说用起来没有链表方便
typedef int QDataType;

//链表节点定义
typedef struct QueueNode 
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* front;
	QNode* rear;
	int size;
}QU;
3.2 需要实现的接口
//队列数据量
int QSize(QU* pq);

//队列的判空
bool QEmpty(QU* pq);

//队列的初始化
void QInit(QU* pq);

//队列的删除
void QDestroy(QU* pq);

//出队
void QPop(QU* pq);

//入队
void QPush(QU* pq, QDataType x);

//取队头
QDataType QFront(QU* pq);

//取队尾
QDataType QBack(QU* pq);
3.3 队列的初始化
  • 队列其实就是带有限制的链表,初始化方式按照链表来就行
//队列的初始化
void QInit(QU* pq)
{
	assert(pq);
	pq->front = NULL;
	pq->rear = NULL;
	pq->size = 0;
}
3.4 队列的删除
  • 删除也是同理,只需要按照链表标准的删除方式就行
//队列的删除
void QDestroy(QU* pq)
{
	assert(pq);
	QNode* cur = pq->front;
	while (cur)
	{
		QNode* lastnode = cur;
		cur = cur->next;
		free(lastnode);
	}
	pq->front = NULL;
	pq->rear = NULL;
	pq->size = 0;
}
3.5 队列的数据量
  • 这里直接返回size就行
//队列数据量
int QSize(QU* pq)
{
	assert(pq);
	return pq->size;
}
3.6 队列的判空
  • 这里我们直接用表达式判空,如果 size 为 0 就返回 true,否则返回 false
//队列的判空
bool QEmpty(QU* pq)
{
	assert(pq);
	return pq->size == 0;
}
3.7 取队头
  • 取队头要保证队列不能为空,要判一下空(当然你用 if 这种不会报错的判空也行)
//取队头
QDataType QFront(QU* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->front->data;
}
3.8 取队尾
  • 和取队头方式一样,只是返回值换成队尾而已
//取队尾
QDataType QBack(QU* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->rear->data;
}
3.9 出队
  • 注意一定要考虑只剩一个数据和没有数据的情况
//出队
void QPop(QU* pq)
{
	assert(pq);
	if (!QEmpty(pq))//这里我们用 if 这种不报错的判空
	{
		QNode* lastnode = pq->front;			//存储当前节点的地址
		if (pq->rear == pq->front)		// 如果只剩下最后一个节点了就先让队尾置为空
		{
			pq->rear = NULL;
		}
		pq->front = pq->front->next;		//让front往后挪,如果只剩一个节点了那front就会变成空
		free(lastnode);			//释放要出队的节点
		pq->size--;		//size减1
	}
}
3.10 入队
  • 入队需要考虑队列里只有一个结点的情况,还需要把申请新节点打包进入队函数里
//入队
void QPush(QU* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)calloc(1, sizeof(QNode));	//队列没有其他函数会申请新节点,我们直接就把申请新节点这个步骤打包进入队里了
	if (newnode == NULL)
	{
		perror("QPush::calloc");
		exit(1);
	}

	newnode->data = x;
	newnode->next = NULL;

	if (pq->rear == NULL)		//如果队列里一个节点都没有,就让 front 和 rear 全部指向新节点
	{
		pq->front = newnode;
		pq->rear = newnode;
	}
	else		//如果队列里已经有节点了,就执行尾插
	{
		pq->rear->next = newnode;
		pq->rear = newnode;
	}
	pq->size++;		//别忘了让 size 加1
}

4 完整实现代码

queue.h

//类型定义

typedef int QDataType;

typedef struct QueueNode
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue
{
	QNode* front;
	QNode* rear;
	int size;
}QU;

//函数定义

//队列数据量
int QSize(QU* pq);

//队列的判空
bool QEmpty(QU* pq);

//队列的初始化
void QInit(QU* pq);

//队列的删除
void QDestroy(QU* pq);

//出队
void QPop(QU* pq);

//入队
void QPush(QU* pq, QDataType x);

//取队头
QDataType QFront(QU* pq);

//取队尾
QDataType QBack(QU* pq);

queue.c

//函数定义

//队列数据量
int QSize(QU* pq)
{
	assert(pq);
	return pq->size;
}

//队列的判空
bool QEmpty(QU* pq)
{
	assert(pq);
	return pq->size == 0;
}

//队列的初始化
void QInit(QU* pq)
{
	assert(pq);
	pq->front = NULL;
	pq->rear = NULL;
	pq->size = 0;
}
 
//队列的删除
void QDestroy(QU* pq)
{
	assert(pq);
	QNode* cur = pq->front;
	while (cur)
	{
		QNode* lastnode = cur;
		cur = cur->next;
		free(lastnode);
	}
	pq->front = NULL;
	pq->rear = NULL;
	pq->size = 0;
}

//出队
void QPop(QU* pq)
{
	assert(pq);
	if (!QEmpty(pq))
	{
		QNode* lastnode = pq->front;
		if (pq->rear == pq->front)
		{
			pq->rear = NULL;
		}
		pq->front = pq->front->next;
		free(lastnode);
		pq->size--;
	}
}

//入队
void QPush(QU* pq, QDataType x)
{
	assert(pq);

	QNode* newnode = (QNode*)calloc(1, sizeof(QNode));
	if (newnode == NULL)
	{
		perror("QPush::calloc");
		exit(1);
	}

	newnode->data = x;
	newnode->next = NULL;

	if (pq->rear == NULL)
	{
		pq->front = newnode;
		pq->rear = newnode;
	}
	else
	{
		pq->rear->next = newnode;
		pq->rear = newnode;
	}
	pq->size++;
}

//取队头
QDataType QFront(QU* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->front->data;
}

//取队尾
QDataType QBack(QU* pq)
{
	assert(pq);
	assert(!QEmpty(pq));
	return pq->rear->data;
}

佬!都看到这了,如果觉得有帮助的话一定要点赞啊佬 >v< !!!

放个卡密在这,感谢各位能看到这儿啦!
请添加图片描述

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值