3.2.2 队列的顺序存储结构

辛苦手码不易, 如若有帮助烦请不吝收藏点赞 😃
静态实现:

#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
    Elemtype data[MaxSize];//用静态数组存放队列元素
    int front,rear;//队头指针和队尾指针
}SqQueue;//Sq 顺序

void testQueue(){
    SqQueue Q;//声明一个顺序队列
    //........后续操作
}

在这里插入图片描述
如上图, 假设队列被分配了五个元素, 则front应指向队头元素(下标0), rear应指向队尾元素的下一个位置, 即插入元素的位置(下标4+1=5)

依照上述逻辑, 在初始化时, 可以让front和rear都指向0, 这同时也可以作为队列判空的标志:

初始化与队列判空:

void InitQueue(SqQueue &Q){//初始化
    Q.rear=Q.front=0;//初始时, 队头队尾指针都指向0
}

void testQueue(){
    SqQueue Q;//声明一个顺序队列
    InitQueue(Q)
    //........后续操作
}

bool QueueEmpty(SqQueue Q){//判空
    if(Q.rear==Q.front)//队空条件
        return ture;
    else
        return false;
}

入队操作:

#define MaxSize 10 //定义队列中元素的最大个数
typedef struct{
    Elemtype data[MaxSize];//用静态数组存放队列元素
    int front,rear;//队头指针和队尾指针
}SqQueue;//Sq 顺序

//入队(只能从队尾入队)
bool EnQueue(SqQueue &Q,ElemType x){
    if((Q.rear+1)%MaxSize==Q.front)//队满条件
        return false;//队满则报错
    Q.data[Q.rear]=x;//新元素插入队尾
    Q.rear=(Q.rear+1)%MaxSize;//队尾指针+1取模
    return true;
}

在这里插入图片描述
对于取模, 我们假设队列Q现在存储了10个元素, 然后出队了3个元素, 即右图所示, 这时, rear==MaxSize

思考: rear==MaxSize是队满条件吗?

假设Q存储10个元素后, 让3个元素从队头出队, 则现在rear=MaxSize, front=3, 显然队不满, 于是每次入队操作后, 对rear+1取模, 即9+1%10=0, rear指针指向了0, 如此, 则rear指针指向了队头, front指针指向了队尾

于是, 我们可以将这样实现的队列理解为一个循环队列
在这里插入图片描述
在这里插入图片描述
出队操作&查队头元素:

//删除一个队头元素, 用x返回
bool DeQueue(SqQueue &Q,ElemType &x){
    if(Q.rear==Q.front)//判断队空
        return false;//队空则报错
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;//队头指针后移:front永远指向第一个存了元素的位置
    return true;
}

//获取队头元素的值, 用x返回
bool GetHeadd(SqQueue Q,ElemType &x){
    if(Q.rear==Q.front)//判断队空
        return false;//队空则报错
    x=Q.data[Q.front];
//省略了队头指针后移操作
    return true;
}

下面着重研究判断队列空/满的几种实现方案

  1. 循环队列

    队满: (Q.rear+1)%MaxSize==Q.front

    队空: Q.rear==Q.front

    缺点: 浪费一个存储空间–>于是, 下列方案2&3不会浪费存储空间

    队列元素个数计算公式: (rear+MaxSize-front)%MaxSize

  2. 定义size变量

    在队列的静态定义时,定义size变量,记录队列当前长度

#define MaxSize 10 
typedef struct{
    Elemtype data[MaxSize];
    int front,rear;
    int size;//在队列的静态定义时,定义size变量,记录队列当前长度
}SqQueue;
//入队成功则size++,出队成功则size--

void InitQueue(SqQueue &Q){//初始化
    Q.rear=Q.front=0;//初始时, 队头队尾指针都指向0
    size=0;
}

//入队(只能从队尾入队)
bool EnQueue(SqQueue &Q,ElemType x){
    if(size==MaxSize)//队满条件
        return false;//队满则报错
    Q.data[Q.rear]=x;//新元素插入队尾
    Q.rear=(Q.rear+1)%MaxSize;//队尾指针+1取模
    size++;
    return true;
}

//删除一个队头元素, 用x返回
bool DeQueue(SqQueue &Q,ElemType &x){
    if(size==0)//判断队空
        return false;//队空则报错
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;//队头指针后移:front永远指向第一个存了元素的位置
    size--;
    return true;
}
  1. 定义tag变量

    思想:

    只有删除操作, 才可能导致队空;

    只有插入操作, 才可能导致队满;

    故:

    每次删除操作成功时, 都令tag=0;

    每次插入操作成功时, 都令tag=1;

    则:

    队满: Q.front==Q.rear&&tag==1

    队空: Q.front==Q.rear&&tag==0

    于是–tag变量记录最近进行的是插入/删除操作

#define MaxSize 10 
typedef struct{
    Elemtype data[MaxSize];
    int front,rear;
    int tag;//在队列的静态定义时,定义tag变量,记录最近进行的是插入/删除操作
}SqQueue;

void InitQueue(SqQueue &Q){//初始化
    Q.rear=Q.front=0;//初始时, 队头队尾指针都指向0
    tag=0;
}

//入队(只能从队尾入队)
bool EnQueue(SqQueue &Q,ElemType x){
    if(Q.front==Q.rear&&tag==1)//队满条件
        return false;//队满则报错
    Q.data[Q.rear]=x;//新元素插入队尾
    Q.rear=(Q.rear+1)%MaxSize;//队尾指针+1取模
    tag=1;
    return true;
}

//删除一个队头元素, 用x返回
bool DeQueue(SqQueue &Q,ElemType &x){
    if(Q.front==Q.rear&&tag==0)//判断队空
        return false;//队空则报错
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;//队头指针后移:front永远指向第一个存了元素的位置
    tag=0;
    return true;
}
  1. 队尾指针rear指向队尾元素时

    初始化时, 队头指针=0, 队尾指针=MaxSize-1

    入队时, 交换rear+1和赋值的顺序

    队空: (Q.rear+1)%MaxSize==Q.front

    队满: 两种方案: 1. 牺牲一个存储空间 (Q.rear+2)%MaxSize==Q.front 2.增加辅助变量size/tag

#define MaxSize 10 
typedef struct{
    Elemtype data[MaxSize];
    int front,rear;
}SqQueue;

void InitQueue(SqQueue &Q){//初始化
    Q.front=0;//初始时, 队头指针指向0
    Q.rear=MaxSize-1;//队尾指针指向n-1
}

//入队(只能从队尾入队)
bool EnQueue(SqQueue &Q,ElemType x){
    if((Q.rear+2)%MaxSize==Q.front)//判断队满:1.牺牲一个存储单元:								(rear+2)%MaxSize==Q.front 2.增加辅助变量size/tag
        return false;//队满则报错
    Q.rear=(Q.rear+1)%MaxSize;//队尾指针+1取模
    Q.data[Q.rear]=x;//新元素插入队尾
    return true;
}

//删除一个队头元素, 用x返回
bool DeQueue(SqQueue &Q,ElemType &x){
    if((Q.rear+1)%MaxSize==Q.front)//判断队空
        return false;//队空则报错
    x=Q.data[Q.front];
    Q.front=(Q.front+1)%MaxSize;//队头指针后移:front永远指向第一个存了元素的位置
    return true;
}

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Autumn_begins

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

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

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

打赏作者

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

抵扣说明:

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

余额充值