数据结构之循环队列C语言实现(详细)[通俗易懂]

数据结构之循环队列C语言实现(详细)[通俗易懂]队列的一些说明队列的定义队列,一种特殊的线性表特点:只允许在一端输入,在另一端输出。输入端称为队尾,输出端称为队头因此,队列,又称为先进先出表(FIFO),类似于生活中的排队,先来的排在前头,后来的排在后头,一个一个办理业务。队列有两种,一种叫做循环队列(顺序队列),另一种叫做链式队列。这一篇讲的是循环队列,链式队列在另外一篇文章中循环数组循环队列使用的是数组,但是这个数组比较特别,为循环数组。为什么要使用循环数组呢?可以想象一下,假如我们使用通常的数组。那么在使用过程中,我们是从后面加

大家好,又见面了,我是你们的朋友全栈君。

队列的一些说明

队列的定义

队列,一种特殊的线性表

特点:只允许在一端输入,在另一端输出。输入端称为队尾,输出端称为队头

因此,队列,又称为先进先出表(FIFO),类似于生活中的排队,先来的排在前头,后来的排在后头,一个一个办理业务。

队列有两种,一种叫做循环队列(顺序队列),另一种叫做链式队列。

这一篇讲的是循环队列,链式队列在另外一篇文章中

链式队列讲解与C++实现

循环数组

循环队列使用的是数组,但是这个数组比较特别,为循环数组。为什么要使用循环数组呢?

可以想象一下,假如我们使用通常的数组。

那么在使用过程中,我们是从后面加入数据,从前面移除数据。那么随着出队和入队的进行,数组会整体向右平移,因为数组前面的元素因为出队变成了空白,变得不可使用。造成空间的浪费。

如果每出队一次,都将数组向左平移一次,又会很麻烦,造成时间上的浪费。综上,我们使用循环队列,就是将队首和队尾黏在一起。类似于一个⚪;
循环数据
那么知道了循环数组后,我们应该考虑下,队首和队尾怎么放置,才能使我们循环队列能够使用。

不同的队首和队尾的初始化,将导致我们判断队列是否已满以及队列是否为空的方法的不同

(1)front(队首)和rear(队尾)初始化均为0。那么,在这种情况下,front会永远指向队首元素,而rear会指向队尾元素的下一格。
(2)front(队首)和rear(队尾)错开。比如 front 初始为0,rear初始为5。在这种情况下front会永远指向队首元素,rear会永远指向队尾元素。

因此,在判断队列是否已满与非空时,初始化不同,判断方式不同。或者干脆就不用front与rear的位置来判断队列是否已满与非空。多加一个参数Size,表示队列的现有容积也行。

另外,如何在代码实现过程中将正常数组变成循环数组呢?

很简单,取余即可

C语言实现循环队列

定义结构体

struct Queue{ 
    //结构体 
 int *data;   
 int capacity; //最大容积 
 int front;  //表头 
 int rear;  //表尾 
 //int size; //size表示队列的现有容量, 
};

队列的初始化

void init(struct Queue *pq,int capacity){ 
    //队列的初始化 
 pq->capacity=capacity;
 pq->data=(int*)malloc(sizeof(int)*(capacity+1));
 pq->front = 0;  //初始化的不同,会导致后面判断队列是否为空以及是否已满的不同 
 pq->rear = 0;
}

判断队列是否已满

int isFull(const struct Queue *pq){ 
     //判断队列是否已满
 if((pq->rear + 1)%(pq->capacity+1) == pq->front) return 1;
 else return 0;
}

判断队列是否为空

int isEmpty(const struct Queue *pq){ 
    //判断是否为空 
 return pq->front == pq->rear;
}

入队操作,x表示插入的元素

int enQueue(struct Queue *pq,int x){ 
    //入队操作 
 if(isFull(pq)) return 0;
 else{ 
   
  pq->data[pq->rear] = x;
  pq->rear = (pq->rear+1) % (pq->capacity+1);
  return 1;  //成功返回1,失败返回0 
 } 
}

出队操作,同时返回出队的值给px

int deQueue(struct Queue *pq,int *px){ 
     //出队操作 
 if(isEmpty(pq)) return 0;
 else { 
   
  *px = pq->data[pq->front];
  pq->front = (pq->front+1) % (pq->capacity+1);
  return 1;  //成功返回1,失败返回0 
 }
}

完整代码

#include<stdio.h>
#include<stdlib.h>
using namespace std;
//循环队列 
struct Queue{ 
    //结构体 
 int *data;   
 int capacity; //最大容积 
 int front;  //表头 
 int rear;  //表尾 
 //int size; //size表示队列的现有容量, 
};

void init(struct Queue *pq,int capacity){ 
    //队列的初始化 
 pq->capacity=capacity;
 pq->data=(int*)malloc(sizeof(int)*(capacity+1));
 pq->front = 0;  //初始化的不同,会导致后面判断队列是否为空以及是否已满的不同 
 pq->rear = 0;
}

int isFull(const struct Queue *pq){ 
     //判断队列是否已满
 if((pq->rear + 1)%(pq->capacity+1) == pq->front) return 1;
 else return 0;
}

int isEmpty(const struct Queue *pq){ 
    //判断是否为空 
 return pq->front == pq->rear;
}

int enQueue(struct Queue *pq,int x){ 
    //入队操作 
 if(isFull(pq)) return 0;
 else{ 
   
  pq->data[pq->rear] = x;
  pq->rear = (pq->rear+1) % (pq->capacity+1);
  return 1;  //成功返回1,失败返回0 
 } 
}

int deQueue(struct Queue *pq,int *px){ 
     //出队操作 
 if(isEmpty(pq)) return 0;
 else { 
   
  *px = pq->data[pq->front];
  pq->front = (pq->front+1) % (pq->capacity+1);
  return 1;  //成功返回1,失败返回0 
 }
}

int main()
{ 
   
 struct Queue q; 
 init(&q,4);
 enQueue(&q,11);
 enQueue(&q,22);
 enQueue(&q,33);
 enQueue(&q,44);
 enQueue(&q,55);
 
 int x;
 deQueue(&q,&x);
 printf("%d\n",x);
  deQueue(&q,&x);
 printf("%d\n",x);
  deQueue(&q,&x);
 printf("%d\n",x);
  deQueue(&q,&x);
 printf("%d\n",x);
  deQueue(&q,&x);
 printf("%d\n",x);
} 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140889.html原文链接:https://javaforall.net

(0)
上一篇 2022年5月26日 下午11:40
下一篇 2022年5月27日 上午6:00


相关推荐

  • Go 版OpenClaw 来了,PicoClaw在GitHub上已经9k star了,附钉钉接入教程+简历写法。

    Go 版OpenClaw 来了,PicoClaw在GitHub上已经9k star了,附钉钉接入教程+简历写法。

    2026年3月12日
    2
  • 漫画:这个靠脸吃饭的男人,太可怕了!

    今天推荐画风唯美的漫画 《重生之星光璀璨》 作为歌坛巨星的阮熙冰被双胞胎妹妹 和未婚夫设计杀害,阴差阳错重生 到了一个小服务生的身上。 她靠着努力与演技重返娱乐圈, 誓要夺回曾属于…

    2021年6月22日
    116
  • js媒体查询

    js媒体查询window onload function onsize window onresize function onsize functiononsi vardeviceWid document documentElem clientWidth

    2026年3月16日
    2
  • 记录自建ALIDDNS服务域名解析和外网访问

    记录自建ALIDDNS服务域名解析和外网访问本文参考https://blog.csdn.net/y1534414425/article/details/90699532除上文外要补充的有AccessKeyID和AccessKeySecret可以使用子账号只需要添加一个AliyunECSReadOnlyAccess权限就可以了需要路由器上虚拟机服务设计端口映射完事就可外网访问了…

    2022年5月2日
    77
  • L2-021 点赞狂魔(排序)「建议收藏」

    L2-021 点赞狂魔(排序)「建议收藏」原题链接微博上有个“点赞”功能,你可以为你喜欢的博文点个赞表示支持。每篇博文都有一些刻画其特性的标签,而你点赞的博文的类型,也间接刻画了你的特性。然而有这么一种人,他们会通过给自己看到的一切内容点赞来狂刷存在感,这种人就被称为“点赞狂魔”。他们点赞的标签非常分散,无法体现出明显的特性。本题就要求你写个程序,通过统计每个人点赞的不同标签的数量,找出前3名点赞狂魔。输入格式:输入在第一行给出一个正整数N(≤100),是待统计的用户数。随后N行,每行列出一位用户的点赞标签。格式为“Name K F​1​

    2022年8月8日
    5
  • 分布式通信协议RPC协议简介

    分布式通信协议RPC协议简介定义RPC(RemoteProcedureCallProtocol)远程过程调用协议,使得我们客户端在不知道调用细节的情况下去调用远程计算机的某个程序中的某个函数时,就跟调用本地函数一样。RPC协议其实是一个规范,其实现框架有Dubbo、Thrift、RMI、WebService、Hessain等。RPC框架的特点是网络协议和网络IO对于调用端和服务端是透明的。RPC框架会封装隐藏底层的通信细节和网络IO细节。服务调用方与服务提供方的调用流程:一个RPC框架应该具有的要素:RPC客户端:

    2022年5月19日
    44

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号