循环队列的顺序存储结构的实现(七)

18.11.24

(基于C语言,欢迎指正)

队列

是一种先进先出(FIFO)的线性表,只允许在队尾进行插入,在队首进行删除

顺序存储的队列写起来跟顺序实现的栈很像,也是采用数组存储数据,但是在不断入队列和出队列过程中,数据会不断后移,所以会造成大量的空间浪费,所以这里我们采用循环队列的形式

循环队列长度

我们需要知道,循环队列也是采用的数组的形式,并且有两个标记位置的整型变量front和rear,其中,front等于队首元素的下标,rear等于队尾元素下一个位置的下标

也就是说,开始时,循环队列长这样
在这里插入图片描述
此时,我们可以发现,循环队列为空,front等于rear

然后我们不断的入队列

最终,循环队列满了,长这样
在这里插入图片描述
我们发现front还是等于rear,于是我们无法通过front和rear判断循环队列是否满了吗?

我们可以不让他满,让他差一点满
像这样
在这里插入图片描述
于是,如果出现front等于rear,那么队列就是空的

那怎么判断队满呢

先假设队列最大长度为 MaxSize
MaxSize这里等于5

我们可以发现

front>=rear
就是这样
在这里插入图片描述
队列的长度为rear-front=5-1=4

front<rear
就是这样
在这里插入图片描述
那么此时,队列长度为rear-front+MaxSize=1-2+5=4

所以,结合上面两种情况,我们可以得出求循环队列长度的通用公式

( rear - front + MaxSize ) % MaxSize

注意这里是取余符号%,不是除法
这个公式子在写循环队列的时候会经常用到,很重要!!!

那么我们开始写循环队列

准备工作

头文件,循环队列的规模,结点的设定,老生常谈的东西了

#include<stdio.h>
#include<stdlib.h>

#define MaxSize 10  //循环队列最多有10-1=9个元素

typedef int QElemType;

typedef struct{     //对循环队列的结点的结构体进行定义
    QElemType data[MaxSize];
    int front;      //头指针指向队首元素
    int rear;       //尾指针指向队尾元素的下一个位置
}SqQueue;

初始化

一开始
在这里插入图片描述
front=rear=0对吧

int InitQueue(SqQueue *Q){//初始化队列
    Q->front=0;
    Q->rear=0;
    return 1;
}

队列长度

我们按照上面的公式
( rear - front + MaxSize ) % MaxSize
代码实现

int Length(SqQueue *Q){//求队列长度
    int len=(Q->rear-Q->front+MaxSize)%MaxSize;
    return len;
}

入队列

我们需要判断队列满的情况,即rear+1==front
代码如下

int EnQueue(SqQueue *Q,QElemType e){//入队列
    if(Length(Q)+1==MaxSize){
        printf("队列已满,数值%d无法进入\n",e);
        return 0;
    }
    Q->data[Q->rear]=e;
    Q->rear=(Q->rear+1)%MaxSize;//rear向后移动一位,若到最后则移动至数组头
    return 1;
}

出队列

我们需要判断队列是否空,即rear!=front才能出队列

int DeQueue(SqQueue *Q,QElemType *e){//出队列,用*e保存出去的值
    if(Q->rear==Q->front){
        printf("队列已空,无法出队列\n");
        return 0;
    }
    *e=Q->data[Q->front];
    Q->front=(Q->front+1)%MaxSize;
    return 1;
}

打印队列元素

有两种情况,如果front>rear,我们就要分段打印

void Print(SqQueue *Q){
    int i=0;
    printf("\n");
    if(Q->front>Q->rear){
        while(Q->front+i==MaxSize){
            printf("%d  ",Q->data[Q->front+i]);
            i++;
        }
        i=0;
        while(i!=Q->rear){
            printf("%d  ",Q->data[i]);
            i++;
        }
    }
    else{
        i=Q->front;
        while(i!=Q->rear){
            printf("%d  ",Q->data[i]);
            i++;
        }
    }
    printf("\n");
}

调试

一些循环队列要用到的基本函数就写完了,下面我们在主函数中进行调试

#include<stdio.h>
#include<stdlib.h>
#define MaxSize 10

typedef int QElemType;

typedef struct{     //对循环队列的结点的结构体进行定义
    QElemType data[MaxSize];
    int front;      //头指针指向队首元素
    int rear;       //尾指针指向队尾元素的下一个位置
}SqQueue;

int InitQueue(SqQueue *Q){//初始化队列
    Q->front=0;
    Q->rear=0;
    return 1;
}

int Length(SqQueue *Q){//求队列长度
    int len=(Q->rear-Q->front+MaxSize)%MaxSize;
    return len;
}

int EnQueue(SqQueue *Q,QElemType e){//入队列
    if(Length(Q)+1==MaxSize){
        printf("队列已满,数值%d无法进入\n",e);
        return 0;
    }
    Q->data[Q->rear]=e;
    Q->rear=(Q->rear+1)%MaxSize;
    return 1;
}

int DeQueue(SqQueue *Q,QElemType *e){//出队列
    if(Q->rear==Q->front){
        printf("队列已空,无法出队列\n");
        return 0;
    }
    *e=Q->data[Q->front];
    Q->front=(Q->front+1)%MaxSize;
    return 1;
}

void Print(SqQueue *Q){
    int i=0;
    printf("\n");
    if(Q->front>Q->rear){
        while(Q->front+i==MaxSize){
            printf("%d  ",Q->data[Q->front+i]);
            i++;
        }
        i=0;
        while(i!=Q->rear){
            printf("%d  ",Q->data[i]);
            i++;
        }
    }
    else{
        i=Q->front;
        while(i!=Q->rear){
            printf("%d  ",Q->data[i]);
            i++;
        }
    }
    printf("\n");
}

int main(){
    int num;//要删除的元素个数
    int e;//用于接收删除的元素
    SqQueue Q;
    InitQueue(&Q);
    for(int i=0;i<12;i++){//入队列
        EnQueue(&Q,i);
    }
    printf("队列长度为:%d \n",Length(&Q));
    Print(&Q);
    printf("输入要删除的元素个数(从队首进行删除)\n");
    scanf("%d",&num);
    for(int i=0;i<num;i++){//偷懒通过循环删除队列
        if(!DeQueue(&Q,&e))
            break;
        printf("删除了一个元素%d,此时队列为:",e);
        Print(&Q);
        printf("\n");
    }
    printf("最终队列为:");
    Print(&Q);
}

结果如下
在这里插入图片描述

  • 13
    点赞
  • 68
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值