队列的简单理解和基本操作

队列

1.1 队列的概念及结构

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

在这里插入图片描述

1.2 队列的实现

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

在这里插入图片描述

1.3 队列的代码实现

文件名功能
Queue.h创建队列,完成函数名的声明
Queue.c实现队列的各个功能函数
test.c测试队列函数的正确性

1.3.1 队列存储的说明

head指针:指向队头元素
tail指针:指向队尾元素
空队时:tail = NULL && head =NULL
队列初始化:tail = head = 0
入队:队未满时,先送值到队尾,再队尾指针加一, 类似于链表的尾插
出队:队为空时,先取队头元素,再队头指针加一, 类似于链表的头删

在这里插入图片描述

1.3.2 队列的定义

typedef int QDataType;
typedef struct QueueNode       //定义队列结点
{
	QDataType data;
	struct QueueNode* next;
}QNode;

typedef struct Queue           //定义队列结构
{
	QNode* head;               //队列头指针
	QNode* tail;               //队列尾指针 
	int sz;                    //计算队列的元素个数
}Queue;

1.3.3 初始化队列

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

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

1.3.4 队列的入队

思路:
类似于单链表的尾插操作, 每次入队前开辟一块空间, 对数据进行尾插, 分清第一次入队和非第一次入队, 同时队列的元素个数增加。

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

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


	if (pq->head == NULL)             //第一次入队
	{
		pq->head = pq->tail = newnode;
	}
	else
	{
		pq->tail->next = newnode;
		pq->tail = newnode;
	}

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

	pq->sz++;
}

1.3.5 队列的出队

思路:
队列中只有一个元素时直接释放此结点(就是队头结点), 否则保存要删除的值指向下一个结点。
队列为空不能出队

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->sz--;
}

1.3.6 获取队头元素

思路:
直接返回队头指针指向的元素。
队列为空不能获取队头元素

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

	return pq->head->data;
}

1.3.7 获取队尾元素

思路:
直接返回队尾指针指向的元素。
队列为空不能获取队尾元素

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

	return pq->tail->data;
}

1.3.8 队列的判空操作

思路:
判断头指针和尾指针是否为空。

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

	return pq->head == NULL && pq->tail == NULL;
}

1.3.9 计算队列的元素个数

思路:
直接返回队列的元素个数
可以不定义sz这个变量直接遍历来得到队列的元素个数, 这样的时间复杂度就是O(n),定义一个变量直接返回队列的元素个数时以空间换时间, 时间复杂度是O(1)。

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

	return pq->sz;
}

1.3.10 销毁队列

思路:
遍历一遍队列直接将结点free。
注意将队头指针和队尾指针置空

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

	QNode* cur = pq->head;

	while (cur)
	{
		QNode* del = cur;      //保存要删除的值, 指向下一个, free掉要删除的值
		cur = cur->next;
		free(del);
	}

	pq->head = pq->tail = NULL;
	pq->sz = 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值