数据结构之循环队列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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • CES Asia专题|用眼睛控制一切,青研科技带来新一代人机交互方式

    CES Asia专题|用眼睛控制一切,青研科技带来新一代人机交互方式

    2022年3月13日
    41
  • linux系统下载官网下载_msdn官网下载系统

    linux系统下载官网下载_msdn官网下载系统CentOS-6.9-x86_64-bin-DVD1.isohttp://archive.kernel.org/centos-vault/6.9/isos/x86_64/CentOS-6.9-x86_

    2022年8月6日
    6
  • Tomcat8zip版本安装与配置[通俗易懂]

    Tomcat8zip版本安装与配置[通俗易懂]Tomcat8zip版本安装配置哈哈哈,又到了紧张刺激的每日必答:在开始之前呢,小Du来来带大家了解几个问题,希望能够在面试中,小Du的解答给你帮助。老样子,话不多说直接上图1.什么Tomcat:答:简单总结下,tomcat是一个中间件,在B/S架构中,浏览器发出的http请求经过tpmcat中间件,转发到最终的目的服务器上,响应消息再通过tomcat返回给浏览器。tomcat所做的事情主要有:开启监听端口监听用户的请求,解析用户发来的http请求然后访问到你指定的应用系统,然后你返回的页面经过t

    2022年6月12日
    26
  • 单片机应用基础知识_51单片机基础知识总结

    单片机应用基础知识_51单片机基础知识总结单片机——硬件基础知识宗旨:技术的学习是有限的,分享的精神是无限的。1、单片机内部资源STC89C52:8KFLASH、512字节RAM、32个IO口、3个定时器、1个UART、8个中断源(1)Flash(硬盘)——程序存储空间——擦写10万次,断电数据不丢失,读写速度慢(2)RAM(内存)——数据存储空间——断电数据丢失

    2025年10月3日
    4
  • APK 签名:v1 v2 v3 v4

    APK 签名:v1 v2 v3 v4通过对Apk进行签名,开发者可以证明对Apk的所有权和控制权,可用于安装和更新其应用。而在Android设备上的安装Apk,如果是一个没有被签名的Apk,则会被拒绝安装。在安装Apk的时候,软件包管理器也会验证Apk是否已经被正确签名,并且通过签名证书和数据摘要验证是否合法没有被篡改。只有确认安全无篡改的情况下,才允许安装在设备上。简单来说,APK的签名主要作用有两个:证明APK的所有者。 允许Android市场和设备校验APK的正确性。

    2022年5月17日
    170
  • es数据库查询API「建议收藏」

    es数据库查询API「建议收藏」1.背景ES数据库是非关系型数据库2.ES数据库优点1.存储优化内存中使用有限状态机FST优化本质上是前缀树加上后缀树的结合,利用这个数据结构可以把Term更节省内存地放置并查询,它有着字典树的查询时间复杂度,但是由于做了后缀合并会更节约内存传统Bitmap优化使用Bitmap来记录文档的Id,每个bit对应一个文档,表示它是否存在。2.联合查询优化若要对多个t…

    2022年5月24日
    273

发表回复

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

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