07队列,图文讲解极其易懂。

4.队列

·相关概念

  1. 定义:只能在表尾进行插入操作,在表头进行删除操作的线性表。 (头插尾删)

  2. 逻辑结构:与线性表相同,仍为一对一关系。

  3. 存储结构:顺序队和链式队都可,但循环顺序队更常用

  4. 运算规则:只能在队首和队尾运算,先进先出(FIFO)原则.与线性表不同(随机存取)。

·队列图解

队列示意图

在这里插入图片描述

常见算法

1. 初始化,入队,出队图解:

在这里插入图片描述

2. 假溢出

概念:尾指针已经指向队列最后,继续入队则会溢出,但由于出队操作导致队列还有有空间,此时称为假溢出(如图)

在这里插入图片描述

解决假溢出方法:
  1. 将队中元素依次向队头方向移动(像现实生活中排队一样)
    缺点:浪费时间

  2. 引入循环队列,队尾指向队头(如图)

在这里插入图片描述

base[0]接在base[MAXOSIZE-1]之后,若rear+1==M,表示尾指针已经到了最后面,则令rear=0;
(由于顺序表无法直接令尾部指向头部所以使用一个新的运算,取模运算)

实现方法:

Q.rear=(Q.rear+1)%MAXQSIZE;     // 当尾指针达到最大值时,回到0
Q.front=(Q.front+1)%MAXQSIZE;   // 当头指针到达最大值时,回到0

在这里插入图片描述

为了避免队空和队满的判断条件一样(如上图),我们采用少用一个元素空间的方式(如下图),类似头结点。
在这里插入图片描述

队满为:(rear+1)%MAXSIZE==front

·具体实现

队列的顺序表示:

  1. 队列的类型定义
#define MAXQSIZE 100    //队列的最大长度
typedef struct {
    int *base;   //队列的基地址用于动态分配空间
    int front;  //队列的头指针(下标)
    int rear;   //队列的尾指针(下标)
}SqQueue;
  1. 循环顺序队初始化
// 循环顺序队初始化(即构造一个空队列)
Status InitStack(SqQueue &Q){
    Q.base=(int*)malloc(MAXQSIZE*sizeof(int));  // 为队列开辟地址(malloc不再赘述)
    if(!Q.base)exit(OVERFLOW);  // 如果base地址为0则表示没有分配成功
    Q.front=Q.rear=0;   //头指针等于尾指针都则为空栈
    return OK;
}
  1. 求队列的长度
// 求队列的长度
int QueueLength(SqQueue Q){
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;  //由于是循环队列,且默认有一个位置为空不存放数据
}

在这里插入图片描述

  1. 循环队列入队

·算法思路:

  1. 判读是否队满,若满则报错(上溢)
  2. 元素e赋值给队尾指针所指的数
  3. 指针++指向下一元素
// 循环队列入队
Status EnQueue(SqQueue &Q,int e){
    if((Q.rear-1)%MAXQSIZE==Q.front)    // 判断队满
        return ERROR;
    Q.base[Q.rear]=e;   //在队尾插入数
    Q.rear=(Q.rear+1)%MAXQSIZE; //队尾指针+1指向下一元素
}
  1. 循环队列出队

·算法思路:

  1. 判断是否队空,若空则报错(下溢)
  2. 获取头指针所指元素,用e返回其指
  3. 头指针–指向下一元素
// 循环顺序队出队
Status DeQueue(SqQueue &Q,int &e){
    if(Q.rear==Q.front)     // 判断队空
        return ERROR;
    e=Q.base[Q.front];  //获取头指针所指元素,用e返回其指
    Q.front=(Q.front+1)%MAXQSIZE;  //队尾指针+1指向下一元素
    return OK;
}
  1. 取队头元素
// 取队头元素
int GetHead(SqQueue Q){
    if(Q.rear==Q.front)     // 判断队是否为空
        return ERROR;
    return Q.base[Q.front];
}

队列的链式表示:

链式实现图解:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q7cmJTM0-1639559068341)(img_10.png)]

  1. 链队列的定义
// 链队列结点的定义:
typedef struct QueueNode{
    int data;
    struct QueueNode *next;
}QueueNode,*QueuePtr;

// 链队列的定义
typedef struct {
    QueuePtr front; //头指针
    QueuePtr rear;  //尾指针
}LinkQueue;
  1. 队列的初始化
// 链队列的初始化(构建空队列):
Status InitQueue(LinkQueue &Q){
//为头指针为指针开指向的空间并令其相等
Q.front=Q.rear=((QueuePtr)malloc(sizeof(QueueNode)));
Q.front->next=NULL; //让头结点的next为空;
return OK;
}
  1. 销毁队列
    算法思想:从头结点开始依次释放所以结点
// 销毁队列
Status DestroyQueue(LinkQueue &Q){
    while(Q.front){
        QueuePtr p;     // 构造一个指针p用于暂时指向被删结点
        p=((QueuePtr)malloc(sizeof(QueueNode)));

        p=Q.front->next;    //让p暂时指向头指针指向结点的下一个结点
        delete Q.front;     //删除头指针指向的结点
        Q.front=p;          //让头指针指向下一个结点;
    }
    return OK;
}
  1. 队列的入队
// 队列的入队
Status EnQueue(LinkQueue &Q,int e){
    QueuePtr p;     // 构造一个指针p用于暂时指向被入队的结点
    p=((QueuePtr)malloc(sizeof(QueueNode)));
    p->data=e;
    p->next=NULL;   //  尾插法
    Q.rear->next=p; // 让p结点与队尾链接
    Q.rear=p;   //新结点成为新的队尾
    return OK;
}
  1. 队列的出队
Status DeQueue(LinkQueue &Q,int e){
    if(Q.front==Q.rear)     //判断队空
        return ERROR;
    QueuePtr p;     // 构造一个指针p用于暂时指向被出队的结点
    p=((QueuePtr)malloc(sizeof(QueueNode)));
    p=Q.front->next;    //指向被出队的结点
    e=p->data;  //e返回出列结点的值
    Q.front->next=p->next;  //头结点指向下一个被出队结点
    if(Q.rear==p)Q.rear=Q.front;    //若尾结点出队,则尾指针指向头结点。
    delete p;   //释放出队结点的空间
    return OK;
}
  1. 取队头元素
// 取队头元素
int GetHead(LinkQueue Q){
    if(Q.rear==Q.front)     //判断队是否为空
        return ERROR;
    return Q.front->next->data;
}
  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

阿明同学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值