栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

文章目录
  • 4.队列
    • ·相关概念
    • ·队列图解
      • 队列示意图
      • 常见算法
        • 1. 初始化,入队,出队图解:
        • 2. 假溢出
          • 解决假溢出方法:
    • ·具体实现
      • 队列的顺序表示:
      • 队列的链式表示:

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;
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/664910.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号