Example004

题目

设计一个循环队列,用 front 和 rear 分别作为队头和队尾指针,另外用一个标志 tag 表示队列是空还是不空,约定当 tag 为 0 时队空,当 tag 为 1 时队不空,这样就可以用 front==rear 作为队满的条件。要求,设计队列的结构和相关基本运算算法(队列元素为 int 型)。

分析

在循环队列中,提供的代码中是占用一个数组空间用来判断是否队满,其实还有其他判断队满的方式,以下就是一种:增设一个 tag 整型变量来标识队列是否为空,如果 tag 为 0 标识队空,如果为 1 则表示队满。在入队和出队算法中,在入队时将 tag 置为 1,因为只有入队操作可能导致队满;在出队时将 tag 置为 0,因为只有出队操作可能导致队空。关于使用 tag 标记后循环队列 queue 的操作如下:

  • 初始化:queue.tag=0; queue.front=queue.rear=0;
  • 队空条件:queue.front==queue.rear&&queue.tag==0
  • 队满条件:queue.front==queue.rear&&queue.tag==1
  • 入队操作:queue.data[queue.rear]=ele; queue.rear=(queue.rear+1)%MAXSIZE; queue.tag=1;
  • 出队操作:ele=queue.data[queue.front]; queue.front=(queue.front+1)%MAXSIZE; queue.tag=0;

注意:

  • 在使用 tag 标记的循环队列中,数组如果最大长度为 MAXSIZE,那么最多能存储 MAXSIZE 个元素。而在提供的循环队列代码中,专门占用了一个数组空间用来判断是否队满,所以最多只能存储 MAXSIZE-1 个元素。
  • 队头指针 front 指向队头元素。队尾指针指向队尾元素的下一个位置。

图解

  • 初始化:

  • 队空:

  • 队非满:

  • 队满

  • 入队

  • 出队

C实现

核心代码:

/*** 将元素入队* @param queue 循环队列* @param ele 待入队的元素* @return 如果返回 1 表示入队成功,否则返回 0 表示入队失败*/
int enQueue(CircularQueue *queue, int ele) {// 0.参数校验,如果队满则返回 0if (queue->front == queue->rear && queue->tag == 1) {return 0;}// 1.将元素入队// 1.1 由于队尾指针指向队尾元素的下一个位置,所以直接填充queue->data[queue->rear] = ele;// 1.2 填充后,修改队尾指针,将其加一,由于是循环队列,所以要对 MAXSIZE 进行取余queue->rear = (queue->rear + 1) % MAXSIZE;// 1.3 修改标记 tag,只要有元素入队,那么队列就会非空,所以置为 1queue->tag = 1;// 1.4 返回 1 表示入队成功return 1;
}/*** 将元素出队* @param queue 循环队列* @param ele 用来保存出队的元素* 如果返回 1 表示出队成功,否则返回 0 表示出队失败*/
int deQueue(CircularQueue *queue, int *ele) {// 0.参数校验,如果为空则不能出队返回 0if (queue->front == queue->rear && queue->tag == 0) {return 0;}// 1.将元素出队// 1.1 保存队头指针所指向的队头元素*ele = queue->data[queue->front];// 1.2 修改队头指针,将其加一,表示删除原队头元素,但由于是循环队列,所以要对 MAXSIZE 取余queue->front = (queue->front + 1) % MAXSIZE;// 1.3 修改标记 tag,出队后队列可能为空,所以将标记置为 0queue->tag = 0;// 1.4 返回 1 表示出队成功return 1;
}

完整代码:

#include<stdio.h>/*** 循环队列中能存储的最大元素个数*/
#define MAXSIZE 5/*** 循环队列结构体定义*/
typedef struct {/*** 循环队列数据域,存储队列中的元素*/int data[MAXSIZE];/*** 指针域,存储队头元素的下标*/int front;/*** 指针域,存储队尾元素的下标*/int rear;/*** 标志,表示队列是空还是不空,约定当 tag 为 0 时队空,当 tag 为 1 时队不空*/int tag;
} CircularQueue;/*** 初始化循环队列* @param queue 未初始化的循环队列*/
void init(CircularQueue *queue) {// 初始化队头和队尾指针,都指向 0queue->front = 0;queue->rear = 0;// 将标志置为 0 表示空队queue->tag = 0;
}/*** 判断循环队列是否为空队列* @param queue 循环队列* @return 如果是空队列则返回 1,否则返回 0*/
int isEmpty(CircularQueue queue) {// 因为标记 tag 用来存储队列是否为空,所以判断标记是否为零即可return queue.front == queue.rear && queue.tag == 0;
}/*** 判断循环队列是否为满* @param queue 循环队列* @return 如果是满队列则返回 1,否则返回 0*/
int isFull(CircularQueue queue) {// 注意,此队列不需要一个额外的空间来判断是否满,所以判断队满的标志是队头指针与队尾指针指向同一个位置// 但前提是队列非空,如果队列为空,那么它们也是指向同一个位置的,所以要加上这个条件return queue.front == queue.rear && queue.tag == 1;
}/*** 将元素入队* @param queue 循环队列* @param ele 待入队的元素* @return 如果返回 1 表示入队成功,否则返回 0 表示入队失败*/
int enQueue(CircularQueue *queue, int ele) {// 0.参数校验,如果队满则返回 0if (queue->front == queue->rear && queue->tag == 1) {return 0;}// 1.将元素入队// 1.1 由于队尾指针指向队尾元素的下一个位置,所以直接填充queue->data[queue->rear] = ele;// 1.2 填充后,修改队尾指针,将其加一,由于是循环队列,所以要对 MAXSIZE 进行取余queue->rear = (queue->rear + 1) % MAXSIZE;// 1.3 修改标记 tag,只要有元素入队,那么队列就会非空,所以置为 1queue->tag = 1;// 1.4 返回 1 表示入队成功return 1;
}/*** 将元素出队* @param queue 循环队列* @param ele 用来保存出队的元素* 如果返回 1 表示出队成功,否则返回 0 表示出队失败*/
int deQueue(CircularQueue *queue, int *ele) {// 0.参数校验,如果为空则不能出队返回 0if (queue->front == queue->rear && queue->tag == 0) {return 0;}// 1.将元素出队// 1.1 保存队头指针所指向的队头元素*ele = queue->data[queue->front];// 1.2 修改队头指针,将其加一,表示删除原队头元素,但由于是循环队列,所以要对 MAXSIZE 取余queue->front = (queue->front + 1) % MAXSIZE;// 1.3 修改标记 tag,出队后队列可能为空,所以将标记置为 0queue->tag = 0;// 1.4 返回 1 表示出队成功return 1;
}/*** 打印循环队列所有元素,从队头到队尾* @param queue 循环队列*/
void print(CircularQueue queue) {// 如果是空队列则单独打印if (queue.front == queue.rear && queue.tag == 0) {printf("[]\n");return;}// 如果是非空队列printf("[");int front = queue.front;// 注意这里使用的的 do...while 循环,因为满队时,队头指针和队尾指针指向同一个位置,所以要先打印一个值再启动循环do {printf("%d", queue.data[front]);if (front != (queue.rear - 1 + MAXSIZE) % MAXSIZE) {printf(", ");}front = (front + 1) % MAXSIZE;} while (front != queue.rear);printf("]\n");
}int main() {// 声明循环队列CircularQueue queue;// 初始化队列printf("\n初始化队列:\n");init(&queue);print(queue);// 队列是否空printf("\n队列是否空:\n");int empty;empty = isEmpty(queue);printf("%d\n", empty);// 将元素入队printf("\n将元素入队:\n");enQueue(&queue, 11);print(queue);enQueue(&queue, 22);print(queue);enQueue(&queue, 33);print(queue);enQueue(&queue, 44);print(queue);enQueue(&queue, 55);print(queue);// 队列是否满printf("\n队列是否满:\n");int full;full = isFull(queue);printf("%d\n", full);// 将元素出队int ele;printf("\n将元素出队:\n");deQueue(&queue, &ele);printf("出队元素:%d\n", ele);print(queue);deQueue(&queue, &ele);printf("出队元素:%d\n", ele);print(queue);deQueue(&queue, &ele);printf("出队元素:%d\n", ele);print(queue);// 队列是否空printf("\n队列是否空:\n");empty = isEmpty(queue);printf("%d\n", empty);
}

执行结果:

初始化队列:
[]队列是否空:
1将元素入队:
[11]
[11, 22]
[11, 22, 33]
[11, 22, 33, 44]
[11, 22, 33, 44, 55]队列是否满:
1将元素出队:
出队元素:11
[22, 33, 44, 55]
出队元素:22
[33, 44, 55]
出队元素:33
[44, 55]队列是否空:
0

Java实现

核心代码:

    /*** 将元素入队** @param ele 待入队的元素* @throws Exception 如果队列已满则不能入队则抛出此异常*/public void enQueue(int ele) throws Exception {// 0.参数校验,如果队满则抛出异常表示不能入队if (isFull()) {throw new Exception("队列已满不能入队!");}// 1.将元素入队// 1.1 由于队尾指针指向队尾元素的下一个位置,所以直接填充queue.data[queue.rear] = ele;// 1.2 填充后,修改队尾指针,将其加一,由于是循环队列,所以要对 MAXSIZE 进行取余queue.rear = (queue.rear + 1) % MAXSIZE;// 1.3 修改标记 tag,只要有元素入队,那么队列就会非空,所以置为 1queue.tag = 1;}/*** 将元素出队** @return 出队元素* @throws Exception 如果队空则不能出队抛出此异常*/public int deQueue() throws Exception {// 0.参数校验,如果为空则不能出队抛出此异常if (isEmpty()) {throw new Exception("队列为空不能出队!");}// 1.将元素出队// 1.1 保存队头指针所指向的队头元素int data = queue.data[queue.front];// 1.2 修改队头指针,将其加一,表示删除原队头元素,但由于是循环队列,所以要对 MAXSIZE 取余queue.front = (queue.front + 1) % MAXSIZE;// 1.3 修改标记 tag,出队后队列可能为空,所以将标记置为 0。queue.tag = 0;// 1.4 返回队头元素return data;}

完整代码:

public class CircularQueue {/*** 循环队列中能存储的最大元素个数*/private final int MAXSIZE = 5;/*** 声明一个循环队列*/private Queue queue;/*** 初始化循环队列*/public void init() {// 实例化对象queue = new Queue();// 为数据域分配存储空间queue.data = new int[MAXSIZE];// 将队头指针和队尾指针都指向 0queue.front = 0;queue.rear = 0;// 将标记置为 0,表示空队列queue.tag = 0;}/*** 判断循环队列是否为空队列** @return 如果是空队列则返回 true,否则返回 false*/public boolean isEmpty() {// 因为标记 tag 用来存储队列是否为空,所以判断标记是否为零即可return queue.front == queue.rear && queue.tag == 0;}/*** 判断循环队列是否为满** @return 如果是满队列则返回 true,否则返回 false*/public boolean isFull() {// 注意,此队列不需要一个额外的空间来判断是否满,所以判断队满的标志是队头指针与队尾指针指向同一个位置// 但前提是队列非空,如果队列为空,那么它们也是指向同一个位置的,所以要加上这个条件return queue.front == queue.rear && queue.tag == 1;}/*** 将元素入队** @param ele 待入队的元素* @throws Exception 如果队列已满则不能入队则抛出此异常*/public void enQueue(int ele) throws Exception {// 0.参数校验,如果队满则抛出异常表示不能入队if (isFull()) {throw new Exception("队列已满不能入队!");}// 1.将元素入队// 1.1 由于队尾指针指向队尾元素的下一个位置,所以直接填充queue.data[queue.rear] = ele;// 1.2 填充后,修改队尾指针,将其加一,由于是循环队列,所以要对 MAXSIZE 进行取余queue.rear = (queue.rear + 1) % MAXSIZE;// 1.3 修改标记 tag,只要有元素入队,那么队列就会非空,所以置为 1queue.tag = 1;}/*** 将元素出队** @return 出队元素* @throws Exception 如果队空则不能出队抛出此异常*/public int deQueue() throws Exception {// 0.参数校验,如果为空则不能出队抛出此异常if (isEmpty()) {throw new Exception("队列为空不能出队!");}// 1.将元素出队// 1.1 保存队头指针所指向的队头元素int data = queue.data[queue.front];// 1.2 修改队头指针,将其加一,表示删除原队头元素,但由于是循环队列,所以要对 MAXSIZE 取余queue.front = (queue.front + 1) % MAXSIZE;// 1.3 修改标记 tag,出队后队列可能为空,所以将标记置为 0。queue.tag = 0;// 1.4 返回队头元素return data;}/*** 打印循环队列所有元素,从队头到队尾*/public void print() {// 如果是空队列则单独打印if (queue.front == queue.rear && queue.tag == 0) {System.out.println("[]");return;}// 如果是非空队列System.out.print("[");int front = queue.front;// 注意这里使用的的 do...while 循环,因为满队时,队头指针和队尾指针指向同一个位置,所以要先打印一个值再启动循环do {System.out.print(queue.data[front]);if (front != (queue.rear - 1 + MAXSIZE) % MAXSIZE) {System.out.print(", ");}front = (front + 1) % MAXSIZE;} while (front != queue.rear);System.out.print("]\n");}
}/*** 循环队列定义*/
class Queue {/*** 循环队列数据域,存储队列中的元素*/int[] data;/*** 指针域,存储队头元素的下标*/int front;/*** 指针域,存储队尾元素的下标*/int rear;/*** 标志,表示队列是空还是不空,约定当 tag 为 0 时队空,当 tag 为 1 时队不空*/int tag;
}

测试代码:

public class CircularQueueTest {public static void main(String[] args) throws Exception {// 声明循环队列CircularQueue queue = new CircularQueue();// 初始化队列System.out.print("\n初始化队列:\n");queue.init();queue.print();// 队列是否空System.out.print("\n队列是否空:\n");boolean empty;empty = queue.isEmpty();System.out.println(empty);// 将元素入队System.out.print("\n将元素入队:\n");queue.enQueue(11);queue.print();queue.enQueue(22);queue.print();queue.enQueue(33);queue.print();queue.enQueue(44);queue.print();queue.enQueue(55);queue.print();// 队列是否满System.out.print("\n队列是否满:\n");boolean full;full = queue.isFull();System.out.println(full);// 将元素出队int ele;System.out.print("\n将元素出队:\n");ele = queue.deQueue();System.out.println("出队元素:" + ele);queue.print();ele = queue.deQueue();System.out.println("出队元素:" + ele);queue.print();ele = queue.deQueue();System.out.println("出队元素:" + ele);queue.print();// 队列是否空System.out.print("\n队列是否空:\n");empty = queue.isEmpty();System.out.println(empty);}
}

执行结果:

初始化队列:
[]队列是否空:
true将元素入队:
[11]
[11, 22]
[11, 22, 33]
[11, 22, 33, 44]
[11, 22, 33, 44, 55]队列是否满:
true将元素出队:
出队元素:11
[22, 33, 44, 55]
出队元素:22
[33, 44, 55]
出队元素:33
[44, 55]队列是否空:
false

队列练习之Example004-设计一个循环队列,用 front 和 rear 分别作为队头和队尾指针,另外用一个标志 tag 表示队列是空还是不空相关推荐

  1. 考研数据结构之队列(3.3)——练习题之设计一个循环队列,用front和rear分别作为队头和队尾指针,另外用一个标志tag表示队列是空还是不空来设计队列的结构和相关基本运算算法(C表示)

    题目 设计一个循环队列,用front和rear分别作为队头和队尾指针,另外用一个标志tag表示队列是空还是不空,约定当tag为0时队空,当tag为1时队不空,这样就可以用front==rear作为队满 ...

  2. 【2011年全国试题3】已知循环队列存储在一维数组A[0…n-1],且队列非空时,front和rear分别指向队头元素和队尾元素。若初始时队列为空,且

    [2011年全国试题3]已知循环队列存储在一维数组A[0-n-1],且队列非空时,front和rear分别指向队头元素和队尾元素.若初始时队列为空,且要求第一个进入队列的元素存储在A[0]处,则初始时 ...

  3. python 消息队列 get是从队首还是队尾取东西_python分布式爬虫中消息队列知识点详解...

    当排队等待人数过多的时候,我们需要设置一个等待区防止秩序混乱,同时再有新来的想要排队也可以呆在这个地方.那么在python分布式爬虫中,消息队列就相当于这样的一个区域,爬虫要进入这个区域找寻自己想要的 ...

  4. python1乘到10_python写一个循环1+到10打印计算步骤的脚本——纯粹无聊玩的

    python写一个循环1+到10打印计算步骤的脚本--纯粹无聊玩的 python写一个循环1+到10打印计算 [root@13cml10 ~]# cat a.py #_*_coding:utf-8_* ...

  5. 力扣-设计一个循环队列

    设计应该支持以下操作: MyCircularQueue(k): 构造器,设置队列长度为 k . Front: 从队首获取元素.如果队列为空,返回 -1 . Rear: 获取队尾元素.如果队列为空,返回 ...

  6. 如何设计一个循环队列

    文章目录 前言 一.思路 二.代码实现 1.MyCircularQueue(k) 构造方法 2.Front 从队首获取元素 3.Rear 获取队尾元素 4.enQueue(value) 向循环队列插入 ...

  7. 栈和队列常见oj题(括号匹配问题、栈实现队列、队列实现栈、设计循环队列)

    一.括号匹配问题 1.题目要求: 2.大体思路 遍历这个字符串,如果是左括号就让它入栈,如果是右括号就让它和栈顶元素进行匹配(前提是栈中有元素),匹配成功的话就让栈顶元素出栈,匹配失败就返回false ...

  8. [js] 使用js实现一个循环队列

    [js] 使用js实现一个循环队列 const queue = [] let queueRunning = false let loopTimer = null const loop = task = ...

  9. 用数组来实现一个循环队列

    1. 初始化 数组 头尾节点 2. 插入 3. 判满 需要预留一个位置,用于判断队列是否满了 如上图发现(rear+1)%maxSize == front;不再插入 4. 删除 如上直接移动front ...

  10. C语言查看队头元素,C语言实现循环队列的初始化进队出队读取队头元素判空-1...

    目前,处在学习数据结构+ing,由于之前学过了队列,今天就把自己写过的代码做了一些完善分享给大家,希望能够帮助到有需要的朋友,有不足的地方欢迎大家交流    φ(゜▽゜*)♪ 队列是另一种限定性的线性 ...

最新文章

  1. 傅里叶变换之看不懂就掐死我教程
  2. 旷视唐文斌:你到底给谁创造了什么样的价值?AI产品灵魂拷问
  3. Docker之HelloWorld篇
  4. python3 socketserver_python3 socketserver
  5. 批量导入数据到mssql数据库的
  6. [数论系列一]C Looooops,跳跳棋,The Luckiest number,CF906D Power Tower,Minimal Power of Prime,仪仗队,LCMSUM
  7. oracle中创建实体,生成实体-SqlSugar 4.x-文档园
  8. panic 苹果aop_Go Web开发之Revel - 拦截器
  9. Qt/C++工作笔记-vector与QVector的拷贝复制(区别与联系)
  10. 10款 非常酷炫的网站首页焦点图 兼容ie浏览器
  11. 进度条小飞机移动动画
  12. 解决windows 7双网卡分别接内外网冲突
  13. office新建文件打开提示文件格式或扩展名无效
  14. Mantle Introduce
  15. 区块链技术及其在信息安全领域的研究进展 简单概括
  16. 新款宝马MINI钥匙增加!轻松搞定,这MINI看着还可以噢
  17. 【爬虫进阶】易班登录加密逆向
  18. sinx泰勒展开_高考中怎么用泰勒公式?
  19. 学计算机大学累不累_大学学计算机专业的体验重点在最后!
  20. Koordinator 0.6:企业级容器调度系统解决方案,引入 CPU 精细编排、资源预留与全新的重调度框架

热门文章

  1. 以下数值中 不能用作C语言标识符,C语言题库及答案(选择题)
  2. 计算机英语总结250字,英语作文250字
  3. 如何实现不规则的Div外部形状?
  4. qt轻松实现不规则按钮
  5. Rasa_nlu_chi:入门教程
  6. Iperf测试WIFI
  7. 【正点原子MP157连载】 第九章 TF-A移植-摘自【正点原子】【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
  8. 罗技键盘的insert键需要按住Fn才能生效?教你修改!
  9. erlang io:format io_lib:format
  10. at91sam9260 OpenWRT u-boot移植