必看!超详细队列详解


前言

前面我们已经学习了栈,今天我们来刨析一下队列的结构

一、队列的概念和结构

只允许一端插入数据,另一端进行删除数据的特殊线性表,其特点是先进先出

入队列:进行插入数据的一端称为队尾
出队列:删除数据的一段称为队头

可以把队列想象成一条水管,先从尾端输入的水,先从队头里面出来,如图:

在这里插入图片描述

那么,队列的底层逻辑该使用数组还是链表呢?使用数组的话,出完队头的数据之后,我们需要把后面所有的元素往前移一步,这样的时间复杂度是比较大的。假如我们使用链表的话,出队列出队列时间复杂度均为O(1),用两个指针,一个指向头结点,一个指向尾结点;出完队头,头指针往后走一步,入队尾,尾指针往后走一部即可

二、队列的实现

1.队列的结构定义

前面我们说了,队列的底层逻辑是链表(所以得先定义结点结构),而且还得有两个指针(用一个结构体变量包含两个指向结点的指针),一个指向头一个指向尾(方便入队列和出队列)。
在这里插入图片描述

下面是代码示例

//以下是头尾结点指针的机构
typedef stuuct Qlistnode
{
    Qlistnode * front;//指向 头结点的指针
    Qlistnode * rear;//指向尾部结点的指针
}Qlist;
//下面是结点的结构
typedef int Quenedatatype;
typedef struct Quene
{
    int data;
    struct Quene * next;
}Quene;

2.队列的初始化

基本思路是:头尾指针均指向NULL,即下图
在这里插入图片描述
代码示例,如下

void Queneinit(Quene * q)//用q指针接收传过来的队列
{
   q->front = q->rear = NULL;//头指针和尾指针均指向NULL
}

3.队列的插入

我们都知道,队列的特点是先入先出,所以是在尾部先插入第一个数据,如下图所示(假设我们插入一个数值为3的结点)
在这里插入图片描述

代码实现,如下:

void Quenepush(Quene * q,Quenedatatype x)
{
   //首先需要判断队列为不为空
   if(q->front == NULL)
   {
      q->front = q->rear = buynode(x);//那么对队列进行插入第一个结点的操作,buynode为创建新节点的函数
   }
   //走到这里说明队列不为空,也就是说队列里面已经有结点了,那么就让rear尾指针指向新的结点
   else
   {
      q->rear->next = buynode(x);//原先的尾结点不再指向空,而是指向新结点
      q->rear = q->rear->next;//尾指针往后面走
   }
}

这就是入队列的代码实现

4.出队列

先进先出,所以出队列是出头指针指向的结点,也就是让头指针向后移一位
如下图

在这里插入图片描述

这就是出队列的图片演示,接下来我们代码实现一下

void Quenepop(Queue * q)
{
    Qnode * pur = q->front->next;//先创建一个pur指针用来指向原先头结点的next结点(也就是图片中2结点)
    free(p->front);//释放掉原先的头结点
    q->front = pur;//头指针重新指向pur指向的结点,即由原先的1指向了2
}

5.获取队列头元素和尾元素

这块相对简单,直接一步带过

//获取队列头元素
Queuedatatype Queuefront(Queue * q)
{
    return q->front->data;
}
//获取队列尾元素
Queuedatatype Queueback(Queue * q)
{
    return q->rear->data;
}

6.判断队列是否为空

队列为不为空的判断条件就是头指针和尾指针其中之一指向NULL,就能说明队列已经为空了

代码如下

int Queueempty(Queue * q)
{
    if(q->front == NULL)
    {
        return 1;
    }
    else
    {
       return 0;
    }
}
int main()
{
    printf("%d",Queueempty(&q));//把队列的地址传过去
    return 0;
}

7.销毁队列

队列的销毁跟我们之前销毁单链表以及双向链表的思路是一样的,可以定义两个指针,一个在前面跑,一个在后面保存

代码如下

void Queuedestory(Queue * q)
{
    Qnode * pur = q->front;//定义pur,指向头结点
    while(pur)
    {
       Qnode * next = pur->next;
       free(pur);
       pur = NULL;
       pur = next;
    }
}

总结

队列和栈一样,都属于比较简单的数据结构,只要有了前面的代码基础,以及队列的的特点———“先进先出”,就可以把队列的知识牢记在脑海里,祝各位学业有成。
这也是博主时隔一个月的再次创作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值