数据结构之队列详解
Posted 梦乡回雪
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之队列详解相关的知识,希望对你有一定的参考价值。
数据结构之队列详解
前言
在介绍玩栈之后我们来介绍下队列基本结构
一、队列的概念及结构
- 队列:只允许在『 一端 』进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有『 先进先出 』 FIFO(First In First Out) 入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头
- 上图演示:
二、队列的实现
- 队列也可以『 数组 』和『 链表 』的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。
『』
1.基本结构
代码如下(示例):
// 链式结构:表示队列
typedef struct QListNode
{
struct QListNode* _pNext;
QDataType _data;
}QNode;
// 队列的结构
typedef struct Queue
{
QNode* _front;
QNode* _rear;
}Queue;
- 这里注意QListNode表示的是每一个『 存放数据 』的节点,Queue是『 整个队列 』,含有指向队头和队尾的两个QListNode* 指针。因此我们在函数传参的时候只需要传递Queue相关的地址来操作队列即可
2.基本操作
(1)初始化和销毁
- 初始化只需要把头尾置空即可,但是销毁不仅仅要销毁队列头尾指针,还要释放每一个存放数据的节点
// 初始化队列
void QueueInit(Queue* q)
{
assert(q);
q->front = q->tail = NULL;
}
// 销毁队列
void QueueDestroy(Queue* q)
{
assert(q);
QueueNode* cur = q->front;
while (cur)
{
QueueNode* next = cur->next;
free(cur);
cur = next;
}
q->front = q->tail = NULL;
}
(2)出队入队
- 队尾入队列,考虑两种情况,一是队列为空直接队列头尾指针指向新节点,二是不为空,需要链接新节点到尾部
// 队尾入队列
void QueuePush(Queue* q, QDataType data)
{
assert(q);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
newnode->data = data;
newnode->next = NULL;
if (q->front == NULL)
{
q->front = q->tail = newnode;
}
else
{
q->tail->next = newnode;
q->tail = newnode;
}
}
- 出队列时候需要特殊注意一种情况,正常做法是把头节点出队free掉,并且头指针指向下一个,但是要考虑只有一个数据出队时候!!!当你头指针释放完指空的时候此刻,尾指针还在指向释放掉的空间,成了野指针!!!因此要置空。
// 队头出队列
void QueuePop(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
QueueNode* next = q->front->next;
free(q->front);
q->front = next;
if (q->front == NULL)
{
q->tail = NULL;
}
}
(3)判空
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0
int QueueEmpty(Queue* q)
{
assert(q);
return q->front == NULL;
}
(4)获取元素
// 获取队列头部元素
QDataType QueueFront(Queue* q)
{
assert(q);//断言防止传进来空指针
assert(!QueueEmpty(q));//断言防止队列空
return q->front->data;
}
// 获取队列队尾元素
QDataType QueueBack(Queue* q)
{
assert(q);
assert(!QueueEmpty(q));
return q->tail->data;
}
// 获取队列中有效元素个数
int QueueSize(Queue* q)
{
assert(q);
int n = 0;
QueueNode* cur = q->front;
while (cur)
{
cur = cur->next;
n++;
}
return n;
}
代码如下(示例):
三、循环队列
- 实际中我们有时还会使用一种队列叫循环队列。环形队列可以使用数组实现也可以用循环链表来实现
- 当头指针和尾指针相遇时队列已满,具体可以参考这篇文章
总结
以上就是队列基础内容和操作,实际上栈和队列的实际应用还是很多,比如叫号机等等。那么队列和栈的常见题型下次见。
以上是关于数据结构之队列详解的主要内容,如果未能解决你的问题,请参考以下文章