用c语言实现——顺序队列支持用户输入交互、入队、出队、查找、遍历、计算队列长度等功能。确定判断判满的方法为:牺牲一个存储单元方式

一、知识介绍

1.基本原理

在顺序队列中,我们使用一个固定大小的数组来存储队列中的元素,并使用两个指针(frontrear)来分别表示队头和队尾的位置。

  1. 队列为空的条件front == rear

  2. 队列满的条件rear + 1 ≡ front (mod MAX_SIZE)

为了区分“队列满”和“队列空”的情况,我们牺牲一个存储单元,即当队尾指针的下一个位置(循环计算)等于队头指针时,认为队列已满,而不是等到队列完全填满。 

2.实现方法 

a.数据结构

b.判空和判满

  • 判空front == rear

  • 判满(rear + 1) % MAX_SIZE == fron

c.入队操作

当队列未满时,将元素添加到队尾,并更新队尾指针:

d.出队操作

当队列非空时,移除队头元素,并更新队头指针:

二、关键点解析

1.判断队列是否已满逻辑解析

 核心逻辑:

队列满的条件是:队尾指针的下一个位置(循环计算)等于队头指针。换句话说,当 (rear + 1) % MAX_SIZE == front 时,队列已满。

为什么这样判断?

  • 循环队列的特性:队列使用一个固定大小的数组来存储元素,并通过 frontrear 指针来管理元素的插入和删除。

  • 牺牲一个存储单元:为了区分“队列满”和“队列空”的情况,我们牺牲一个存储单元。
    rear + 1 等于 front 时,认为队列已满,而不是等到队列完全填满。

假设 MAX_SIZE = 5,队列的数组大小为 5。
情况 1:队列满:
front = 0
rear = 4
(4 + 1) % 5 = 0,等于 front,所以队列满。
情况 2:队列未满
front = 0
rear = 3
(3 + 1) % 5 = 4,不等于 front,所以队列未满。

2. 入队逻辑

a. 判断队列是否已满

调用 IsFull 函数判断队列是否已满。

如果队列已满,打印提示信息并返回 false,表示入队失败。

b.入队操作

 将元素 value 存入队列的尾部位置(q->rear)。

c.更新队尾指针

队尾指针 rear 加 1,并对数组大小 MAX_SIZE 取模,是为了确保指针在数组范围内循环。

d. 返回成功 

3.出队逻辑

a.函数定义

返回值类型:bool,表示出队操作是否成功。

参数:

SeqQueue *q:指向队列的指针。

int *value:指向一个整型变量的指针,用于存储出队的元素值。

b.判断队列是否为空

调用 IsEmpty 函数判断队列是否为空。

如果队列为空,打印提示信息并返回 false,表示出队失败。

c.获取队头元素

将队列中队头位置(q->front)的元素值赋给传入的指针变量 *value

  • q->data 是存储队列元素的数组。

  • q->front 是队头指针,指向当前队列的第一个元素的位置。

  • q->data[q->front] 通过数组索引访问队头元素。

  • *value 是一个指针解引用操作,将队头元素的值存储到传入的变量中。

d.更新队头指针

队头指针 front 加 1,并对数组大小 MAX_SIZE 取模,确保指针在数组范围内循环。

4.查找元素

a.检查队列是否为空

调用 IsEmpty 函数判断队列是否为空。

如果队列为空,打印提示信息并返回 -1,表示无法查找。

b. 初始化变量

index:初始化为队头指针 front,用于遍历队列。

count:初始化为0,用于记录当前遍历到的位置。

c. 遍历队列

循环条件:index != q->rear,表示队列中还有元素未遍历。

查找逻辑:

       如果当前索引位置的元素等于要查找的值,返回 count,从0开始表示找到了元素。

       如果未找到,更新 index 指针为下一个位置,并对数组大小 MAX_SIZE 取模,确保指针在数组范围内循环。

   count 加1,记录当前遍历到的位置。

d.未找到元素

如果循环结束仍未找到元素,返回 -1

5.遍历逻辑

a.检查队列是否为空

调用 IsEmpty 函数判断队列是否为空。

如果队列为空,打印提示信息并返回,表示无法遍历。

b.打印队列元素并遍历

打印提示信息,表示接下来将输出队列中的元素。

初始化索引index 初始化为队头指针 front,用于遍历队列。

循环条件index != q->rear,表示队列中还有元素未遍历。

打印元素:通过 q->data[index] 访问当前索引位置的元素并打印。

更新索引index = (index + 1) % MAX_SIZE,更新索引为下一个位置,并对数组大小 MAX_SIZE 取模,确保指针在数组范围内循环。

打印换行符,使输出更整洁。

6.计算长度逻辑

a.为什么可以这样计算?

1. 直接计算 rear - front

在非循环队列中,队列的长度可以直接通过 rear - front 计算。例如:

  • 如果 front = 0rear = 3,队列长度为 3 - 0 = 3

  • 如果 front = 1rear = 4,队列长度为 4 - 1 = 3

2. 循环队列的特殊情况

在循环队列中,rear 可能小于 front,因为队列是循环的。例如:

  • 如果 front = 3rear = 0,直接计算 rear - front 会得到负数 -3,这显然不符合实际队列长度。

3. 解决负数问题

为了避免负数,公式中加上了 MAX_SIZE

这样可以确保结果始终是正数。例如:

  • 如果 front = 3rear = 0MAX_SIZE = 5

    • 0 - 3 + 5 = 2,表示队列中有 2 个元素。

4. 取模操作

这一步确保即使 rearfront 的差值超过 MAX_SIZE,结果仍然正确

假设 MAX_SIZE = 5

情况 1:rear 大于 front
  • front = 0

  • rear = 3

  • 计算:(3 - 0 + 5) % 5 = 8 % 5 = 3,队列长度为 3。

情况 2:rear 小于 front
  • front = 3

  • rear = 0

  • 计算:(0 - 3 + 5) % 5 = 2 % 5 = 2,队列长度为 2。

情况 3:队列为空
  • front = 0

  • rear = 0

  • 计算:(0 - 0 + 5) % 5 = 5 % 5 = 0,队列长度为 0。

三、完整代码

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>#define MAX_SIZE 10                              // 队列的最大容量                      // 定义队列结构
typedef struct
{int data[MAX_SIZE];                          // 存储队列元素的数组             int front;                                   // 队头指针int rear;                                    // 队尾指针
}SeqQueue;// 初始化队列
void InitQueue(SeqQueue* q)
{q->front = 0;q->rear = 0;
}// 判断队列是否已满
bool isFull(SeqQueue* q)
{return ((q->rear + 1) % MAX_SIZE) == q->front;
}// 判断队列是否为空
bool isEmpty(SeqQueue* q)
{return	q->front == q->rear;
}// 入队操作
bool Enqueue(SeqQueue* q, int value)
{if (isFull(q)){printf("队列已满,无法入队!\n");return false;}q->data[q->rear] = value;q->rear = (q->rear + 1) % MAX_SIZE;return true;
}// 出队操作
bool Dequeue(SeqQueue* q, int* value)
{if (isEmpty(q)){printf("队列为空,无法出队!\n");return false;}*value = q->data[q->front];q->front = (q->front + 1) % MAX_SIZE;return true;
}// 查找元素
int FindElement(SeqQueue* q, int value)
{if (isEmpty(q)){printf("队列为空,无法查找!\n");return -1;}int index = q->front;int count = 1;while (index != q->rear){if (q->data[index] == value){return count;                         // 返回元素在队列中的位置(从0开始)}index = (index + 1) % MAX_SIZE;count++;}return -1;
}// 遍历队列
void TraverseQueue(SeqQueue* q)
{if (isEmpty(q)){printf("队列为空,无法遍历!\n");return;}printf("队列元素:");int index = q->front;while (index != q->rear){printf("%d ", q->data[index]);index = (index + 1) % MAX_SIZE;}printf("\n");
}// 计算队列长度
int QueueLength(SeqQueue* q)
{return ((q->rear) - (q->front) + MAX_SIZE) % MAX_SIZE;
}void Menu()
{printf("\n===== 顺序队列操作菜单 =====\n");printf("1. 入队\n");printf("2. 出队\n");printf("3. 查找元素\n");printf("4. 遍历队列\n");printf("5. 计算队列长度\n");printf("0. 退出程序\n");printf("请输入您的选择:");
}int main()
{SeqQueue queue;InitQueue(&queue);int choice = 0;int value = 0;int pos = 0;while (1){Menu();scanf_s("%d", &choice);switch (choice){case 1:printf("请输入要入队的元素:>");scanf_s("%d", &value);if (Enqueue(&queue, value)){printf("入队成功!当前队列长度:>%d\n", QueueLength(&queue));}break;case 2:if (Dequeue(&queue, &value)){printf("出队元素:%d,当前队列长度:%d\n", value, QueueLength(&queue));}break;case 3:printf("请输入要查找的元素:");scanf_s("%d", &value);pos = FindElement(&queue, value);if (pos != -1){printf("元素 %d 在队列中的位置为:%d\n", value, pos);}else{printf("队列中不存在元素 %d\n", value);}break;case 4:TraverseQueue(&queue);break;case 5:printf("当前队列长度:%d\n", QueueLength(&queue));break;case 0:printf("程序结束!\n");exit(0);break;default:printf("无效的选择,请重新输入!\n");}}return 0;
}

 以上是基于VS2022编译器,用c语言实现——顺序队列。判断队列已满或者空的情况是通过牺牲一个存储单元的方法来实现的。支持用户输入交互、入队、出队、查找、遍历等功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/77449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM 系列:JVM 内存结构深度解析

你点赞了吗&#xff1f;你关注了吗&#xff1f;每天分享干货好文。 高并发解决方案与架构设计。 海量数据存储和性能优化。 通用框架/组件设计与封装。 如何设计合适的技术架构&#xff1f; 如何成功转型架构设计与技术管理&#xff1f; 在竞争激烈的大环境下&#xff0c…

手机上的APN是什么,该怎么设置

网上说改个APN就可以让网速快几倍&#xff0c;那到底APN是个什么东西&#xff0c;真的能让网速快几倍吗&#xff1f; APN的作用 网络连接基础&#xff1a;APN&#xff08;接入点名称&#xff09;是手机连接移动网络的“桥梁”&#xff0c;负责识别运营商网络类型&#xff08;…

微服务治理与可观测性

服务注册与发现 核心功能 服务实例动态变化&#xff1a;实例可能因扩缩容、故障或迁移导致IP变动。服务依赖解耦&#xff1a;调用方无需硬编码服务地址&#xff0c;降低耦合度。负载均衡&#xff1a;自动选择健康实例&#xff0c;提升系统可用性。 核心组件 服务注册中心&am…

嵌入式linux系统中内存管理的方法与实现

第一:linux内核管理详解图形 第二:Linux内存管理详细分析 深入剖析Linux内核内存管理 作为嵌入式系统开发者,理解Linux内核的内存管理对于开发高效、稳定的系统至关重要。在这篇文章中,我们将详细解析Linux内核如何划分物理内存和虚拟内存,页表、MMU(内存管理单元)与TL…

【dataframe显示不全问题】打开一个行列超多的excel转成df之后行列显示不全

出现问题如下图&#xff1a; 解决方案&#xff5e; display.width解决列显示不全 pd.set_option(display.max_columns,1000) pd.set_option(display.width, 1000) pd.set_option(display.max_colwidth,1000) pd.set_option(display.max_rows,1000)

Linux——Shell编程之正则表达式与文本处理器(笔记)

目录 基础正则表达式 1:基础正则表达式示例 &#xff08;4&#xff09;查找任意一个字符“.”与重新字符“*” &#xff08;5&#xff09;查找连续字符范围“{ }” 文本处理器 一、sed工具 二、awk工具 &#xff08;1&#xff09;按行输出文本 &#xff08;2&#xff0…

OpenHarmony系统-源码下载,环境搭建,编译,烧录,调试

获取源码 以OpenHarmony5.0.3为例 repo init -u https://gitee.com/openharmony/manifest -b OpenHarmony-5.0.3-Release --no-repo-verify repo sync -c repo forall -c git lfs pull搭建环境 安装必要的工具和命令 apt-get install -y apt-utils binutils bison flex bc …

Vue3 本地打包启动白屏解决思路!! !

“为什么我访问 http://127.0.0.1:5501/index.html 白屏&#xff0c;删了 index.html 再访问 / 就又活过来了&#xff1f;” —— 你的项目与 SPA 路由的“宫斗大戏” 一、问题复现 场景 本地通过 VSCode Live Server&#xff08;或其他静态服务器&#xff09;启动了打包后的 V…

数字人(2):数字人技术全景透视(2025演进版)

随着人工智能技术的迅猛发展,数字人技术发展也是一日千里。站在当下,着眼未来,我们一起在回眸透视过去的基础上,一起共同眺望数字人技术的未来。 一、数字人技术体系重构 我们可以用三维定义对数字人技术进行框架重构 维度 技术内涵 典型特征 物理层 人体数字化建模技术 …

小刚说C语言刷题——1035 判断成绩等级

1.题目描述 输入某学生成绩&#xff0c;如果 86分以上(包括 86分&#xff09;则输出 VERY GOOD &#xff0c;如果在 60到 85之间的则输出 GOOD (包括 60和 85)&#xff0c;小于 60 的则输出 BAD。 输入 输入只有一行&#xff0c;包括 1个整数。 输出 输出只有一行&#xf…

React-在使用map循环数组渲染列表时须指定唯一且稳定值的key

在渲染列表的时候&#xff0c;我们须给组件或者元素分配一个唯一值的key, key是一个特殊的属性&#xff0c;不会最终加在元素上面&#xff0c;也无法通过props.key来获取&#xff0c;仅在react内部使用。react中的key本质是服务于diff算法, 它的默认值是null, 在diff算法过程中…

Zookeeper的通知机制是什么?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper的通知机制是什么&#xff1f;】面试题。希望对大家有帮助&#xff1b; Zookeeper的通知机制是什么&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 的通知机制是其核心特性之一&#xf…

【LangChain实战】构建下一代智能问答系统:从RAG架构到生产级优化

打破传统问答系统的次元壁 当ChatGPT在2022年掀起AI革命时&#xff0c;开发者们很快发现一个残酷现实&#xff1a;通用大模型在专业领域的表现如同拿着地图的盲人&#xff0c;既无法理解企业私有数据&#xff0c;也无法保证事实准确性。这催生了RAG&#xff08;检索增强生成&a…

UDS中功能寻址可以请求多帧数据嘛?当ECU响应首帧后,诊断仪是通过物理寻址发送流控帧嘛?

文章目录 1. 前言📢1.1 功能寻址是否支持请求多帧数据?1.2 ECU发送首帧(FF)后,诊断仪如何发送流控帧(FC)?1.3 协议依据(ISO 14229-1)1.4 实际应用注意事项总结1. 前言📢 在UDS(Unified Diagnostic Services)协议中,功能寻址与物理寻址的使用规则以及多帧数据传…

PHP异常处理__Throwable

在 PHP 里&#xff0c;Throwable 是一个极为关键的接口&#xff0c;自 PHP 7 起被引入。它为错误和异常处理构建了一个统一的框架。下面会详细介绍 Throwable 的相关内容。 1. 基本概念 Throwable 是 Exception 和 Error 的父接口。在 PHP 7 之前&#xff0c;异常&#xff08…

无需训练的具身导航探索!TRAVEL:零样本视觉语言导航中的检索与对齐

作者&#xff1a; Navid Rajabi, Jana Kosecka 单位&#xff1a;乔治梅森大学计算机科学系 论文标题&#xff1a;TRAVEL: Training-Free Retrieval and Alignment for Vision-and-Language Navigation 论文链接&#xff1a;https://arxiv.org/pdf/2502.07306 主要贡献 提出…

Vue3+Vite+TypeScript+Element Plus开发-22.客制Table组件

系列文档目录 Vue3ViteTypeScript安装 Element Plus安装与配置 主页设计与router配置 静态菜单设计 Pinia引入 Header响应式菜单缩展 Mockjs引用与Axios封装 登录设计 登录成功跳转主页 多用户动态加载菜单 Pinia持久化 动态路由 -动态增加路由 动态路由-动态删除…

Java读取JSON文件并将其中元素转为JSON对象输出

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Java读取JSON文件并将其中元素转为JSON对象输…

Spring Boot自动配置原理深度解析:从条件注解到spring.factories

大家好&#xff01;今天我们来深入探讨Spring Boot最神奇的特性之一——自动配置(Auto-configuration)。这个功能让Spring Boot如此受欢迎&#xff0c;因为它大大简化了我们的开发工作。让我们一起来揭开它的神秘面纱吧&#xff01;&#x1f440; &#x1f31f; 什么是自动配置…

【ELF2学习板】利用OpenMP采用多核并行技术提升FFTW的性能

目录 引言 OpenMP简介 编译OpenMP支持的FFTW库 部署与测试 测试程序 程序部署 测试结果 结语 引言 在前面已经介绍了在ELF2开发板上运行FFTW计算FFT。今天尝试利用RK3588的多核运算能力来加速FFT运算。FFTW利用多核能力可以考虑使用多线程或者OpenMP。今天介绍一下Ope…