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


相关推荐

  • 【SC随笔】Java测试mutator方法的注意点

    【SC随笔】Java测试mutator方法的注意点对于mutator方法,仅仅测试返回值是否符合预期是不完备的,mutator改变了对象,就需要用observor方法观察是否发生了预期改变

    2025年11月4日
    7
  • Method类的Invoke方法[通俗易懂]

    Method类的Invoke方法[通俗易懂]Dto:dto里面放的都是同一类型的字段/**Creation:2Dec2015*/packagecom.java.invoke;publicclassDto{privateIntegerCol1;privateIntegerCol2;privateIntegerCol3;privateIntegerCo

    2022年6月1日
    38
  • 股指期货跨期套利策略优化_股指期现套利策略盈亏

    股指期货跨期套利策略优化_股指期现套利策略盈亏股指期货跨期套利策略概述:本文章介绍使用同一标的不同交割日的股指期货的价差进行跨期套利的策略。本文由JoinQuant量化课堂推出,难度为进阶(下),深度为level-0。​作者:swlaw编辑

    2022年8月6日
    8
  • JVM类加载过程

    1.JVM类加载过程1.概述从类的生命周期而言,一个类包括如下阶段:加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的,类的加载过程必须按照这种顺序进行,而解析阶段则不一定,它在某些情况下可能在初始化阶段后在开始,因为java支持运行时绑定。2.类加载时机加载(loading)阶段,java虚拟机规范中没有…

    2022年4月4日
    58
  • 另类走遍美国的生活语言:美国黑话英语大观(详解)

    另类走遍美国的生活语言:美国黑话英语大观(详解)文章来源:生活是语言美国的黑人社会中的帮派问题经常地在绕舌歌曲中被讨论,自然也有许多与帮派相关的黑话会常在绕舌歌中出现,如:O.G.-即OriginalGangster,用来指有案底的帮派份子。redrum-就是谋杀(murder)的意思,只是这里把它反过来写。Rolling60s-一黑帮的支派。set-帮派分支。Settripping-帮派内斗。

    2022年5月12日
    78
  • 地表最强app官网ios_地表最强app下载

    地表最强app官网ios_地表最强app下载1.全历史当你村里的二大爷,国外回来的Uncle刘想要和你交流交流历史时,没关系,查看这个App。从生命起源到现代文明,从东亚到北美洲,从政权到经济,从军事到民生,保证让你上知天文,下知地理,聊得你二大爷也很蒙圈。2.Canva朋友相聚怎么少的了拍照发朋友圈!Canva提供朋友圈拍照模板以及各种特效,可爱的,青春的,春节气氛的,统统都有。万一结个婚呢,还可以在上面做贺卡。3.美丽修行…

    2022年8月22日
    14

发表回复

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

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