数据结构——队列

一、定义

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出的特性。

队尾:进行插入操作的一端。

队头:进行删除操作的一端。

二、结构体定义

// 链式结构:表示队列 
typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* front;//队头
	QNode* rear;//队尾
}Queue;

若采用顺序表的方式实现队列,随着出队入队的操作,队头指针和队尾指针的移动,队头前的空间就可能发生内存泄漏,或出现假溢出问题。对此有两种解决方法,一种是采用链表的方式实现队列,一种是采用循环队列,这里采用的是链表的方式实现队列,随后会发布循环队列的实现方法。

三、接口实现

void Queue_Tese();//队列功能测试函数
QNode* buyQNode(QDataType data);//带头结点的单链表
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);// 获取队列中有效元素个数 
int QueueEmpty(Queue* q);// 检测队列是否为空,为空返回1,非空返回0 
void QueueDestroy(Queue* q);// 销毁队列 

1.创建带头结点的单链表

QNode* buyQNode(QDataType data) {//带头结点的单链表
	QNode* newNode = (QNode*)malloc(sizeof(QNode));
	if (newNode == NULL) {
		assert(0);
		return NULL;
	}
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

使用带头结点的单链表实现队列,可以简化实现过程的很多操作。

2.初始化队列

void QueueInit(Queue* q) {// 初始化队列
	assert(q);
	q->front = buyQNode(0);
	q->rear = q->front;
}

将队列头尾指针都指向头结点即可。

3.入队

void QueuePush(Queue* q, QDataType data) {// 队尾入队列 
	assert(q);
	QNode* newNode = buyQNode(data);
	q->rear->next = newNode;
	q->rear = newNode;
}

只能在队尾入队。

4.判空

int QueueEmpty(Queue* q) {// 检测队列是否为空,为空返回1,非空返回0 
	assert(q);
	return q->front == q->rear;
}

队头队尾指针都在初始位置指向头结点,即队列为空,若用顺序表实现则是队头队尾都在0号位置即队列为空。

5.出队

void QueuePop(Queue* q){// 队头出队列 
	assert(q);
	if (QueueEmpty(q)) {//判空
		return;
	}
	QNode* delNode = q->front->next;
	q->front->next = delNode->next;
	if (delNode == q->rear) {//若队列只有一个元素,出队列后要将队尾放到头结点处
		q->rear = q->front;
	}
	free(delNode);
}

出队列只能在队头出队。因为这里采用的是带头结点的单链表实现队列,所以在队列只有一个元素时出队列,需要把队尾指针放回到头节处。

6.获取队头

QDataType QueueFront(Queue* q) {// 获取队列头部元素 
	assert(q);
	return q->front->next->data;
}

7.获取队尾

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

8.获取队列中有效元素个数

int QueueSize(Queue* q) {// 获取队列中有效元素个数 
	assert(q);
	QNode* cur = q->front->next;
	int len = 0;
	while (cur) {
		len++;
		cur = cur->next;
	}
	return len;
}

通过单链表的遍历计数实现。

9.队列销毁

void QueueDestroy(Queue* q) {// 销毁队列
	assert(q);
	QNode* cur = q->front->next;
	while (cur) {
		q->front->next = cur->next;
		free(cur);
		cur = q->front->next;
	}
	free(q->front);
	q->front = q->rear = NULL;
}

循环释放每个结点,最后置空头尾指针。

四、接口测试

1.测试用例

void Queue_Tese() {//队列功能测试函数
	Queue q;
	QueueInit(&q);
	printf("size = %d\n", QueueSize(&q));

	// 入队列
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	QueuePush(&q, 6);
	QueuePush(&q, 7);
	printf("\nsize = %d\n", QueueSize(&q));
	printf("front = %d\n", QueueFront(&q));
	printf("back = %d\n", QueueBack(&q));

	// 出队列
	QueuePop(&q);
	printf("\nsize = %d\n", QueueSize(&q));
	printf("front = %d\n", QueueFront(&q));
	printf("back = %d\n", QueueBack(&q));

	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	printf("\nsize = %d\n", QueueSize(&q));
	printf("front = %d\n", QueueFront(&q));
	printf("back = %d\n", QueueBack(&q));

	QueuePop(&q);
	QueuePop(&q);
	printf("\nsize = %d\n", QueueSize(&q));
	QueueDestroy(&q);
}

2.测试结果

五、完整代码

#include<stdio.h>
#include<assert.h>
#include<malloc.h>

// 链式结构:表示队列 
typedef int QDataType;
typedef struct QListNode
{
	struct QListNode* next;
	QDataType data;
}QNode;

// 队列的结构 
typedef struct Queue
{
	QNode* front;//队头
	QNode* rear;//队尾
}Queue;
void Queue_Tese();//队列功能测试函数
QNode* buyQNode(QDataType data);//带头结点的单链表
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);// 获取队列中有效元素个数 
int QueueEmpty(Queue* q);// 检测队列是否为空,为空返回1,非空返回0 
void QueueDestroy(Queue* q);// 销毁队列 

int main() {
	Queue_Tese();
	return 0;
}

QNode* buyQNode(QDataType data) {//带头结点的单链表
	QNode* newNode = (QNode*)malloc(sizeof(QNode));
	if (newNode == NULL) {
		assert(0);
		return NULL;
	}
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

void QueueInit(Queue* q) {// 初始化队列
	assert(q);
	q->front = buyQNode(0);
	q->rear = q->front;
}

void QueuePush(Queue* q, QDataType data) {// 队尾入队列 
	assert(q);
	QNode* newNode = buyQNode(data);
	q->rear->next = newNode;
	q->rear = newNode;
}

int QueueEmpty(Queue* q) {// 检测队列是否为空,为空返回1,非空返回0 
	assert(q);
	return q->front == q->rear;
}

void QueuePop(Queue* q){// 队头出队列 
	assert(q);
	if (QueueEmpty(q)) {//判空
		return;
	}
	QNode* delNode = q->front->next;
	q->front->next = delNode->next;
	if (delNode == q->rear) {//若队列只有一个元素,出队列后要将队尾放到头结点处
		q->rear = q->front;
	}
	free(delNode);
}

QDataType QueueFront(Queue* q) {// 获取队列头部元素 
	assert(q);
	return q->front->next->data;
}

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

int QueueSize(Queue* q) {// 获取队列中有效元素个数 
	assert(q);
	QNode* cur = q->front->next;
	int len = 0;
	while (cur) {
		len++;
		cur = cur->next;
	}
	return len;
}

void QueueDestroy(Queue* q) {// 销毁队列
	assert(q);
	QNode* cur = q->front->next;
	while (cur) {
		q->front->next = cur->next;
		free(cur);
		cur = q->front->next;
	}
	free(q->front);
	q->front = q->rear = NULL;
}

void Queue_Tese() {//队列功能测试函数
	Queue q;
	QueueInit(&q);
	printf("size = %d\n", QueueSize(&q));

	// 入队列
	QueuePush(&q, 1);
	QueuePush(&q, 2);
	QueuePush(&q, 3);
	QueuePush(&q, 4);
	QueuePush(&q, 5);
	QueuePush(&q, 6);
	QueuePush(&q, 7);
	printf("\nsize = %d\n", QueueSize(&q));
	printf("front = %d\n", QueueFront(&q));
	printf("back = %d\n", QueueBack(&q));

	// 出队列
	QueuePop(&q);
	printf("\nsize = %d\n", QueueSize(&q));
	printf("front = %d\n", QueueFront(&q));
	printf("back = %d\n", QueueBack(&q));

	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	QueuePop(&q);
	printf("\nsize = %d\n", QueueSize(&q));
	printf("front = %d\n", QueueFront(&q));
	printf("back = %d\n", QueueBack(&q));

	QueuePop(&q);
	QueuePop(&q);
	printf("\nsize = %d\n", QueueSize(&q));
	QueueDestroy(&q);
}

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hey小孩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值