C语言_数据结构总结7:顺序队列(循环队列)

news/2025/3/13 17:33:52/

  纯C语言实现,不涉及C++  

队列

简称队,也是一种操作受限的线性表。只允许表的一端进行插入,表的另一端进行删除
特性:先进先出

针对顺序队列存在的“假溢出”问题,引出的循环队列概念。


循环队列
将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环。
当队首指针Q->front=MaxSize-1 后,再前进一个位置就自动到0,这可以利用除法取余运算(%)来实现。

循环队列中的判空和判满条件分析:
显然,队空的条件是Q.front == Q.rear。但若入队元素的速度快于出队元素,则队尾指针很快就会追赶上队首指针。
此时可以看出队满时也有:Q.front == Q.rear.
为此,有3中处理方法:
1. (推荐)牺牲一个单元来区分队空和队满,入队时少用一个队列单元,这是一种较为普遍的做法,约定“队头指针在队尾指针的下一个位置作为队满标志”
队满条件:(Q.rear + 1) % MaxSize == Q.front;
队空条件:Q.front == Q.rear;
队列中元素的个数:(Q.rear - Q.front + MaxSize) % MaxSize;

2. 在定义存储类型中,增设size数据成员,表示元素个数。
删除元素成功size减1;插入元素成功size加1.
队满时:Q.size == MaxSize;
队空时:Q.size == 0;
队空和队满时都有:Q.front == Q.rear;

3. 在定义存储类型中,增设tag数据成员,以区分是队满还是队空。
删除元素成功置tag=0,若导致Q.front == Q.rear;则为队空
插入元素成功置tag=1,若导致Q.front == Q.rear;则为队空

顺序队列(循环队列)的基本操作:

以下使用的方法是第一种处理方法,即牺牲一个单元来区分队空和队满。

0.  存储结构


#include<stdio.h>
#define MaxSize 50
typedef int ElemType;typedef struct SqQueue {ElemType data[MaxSize];  // 用数组存放队列元素int front;  // 队头指针.负责出队int rear;   //队尾指针,负责进队
}SqQueue;

1. 初始化

void InitQueue(SqQueue* Q) {Q->front = 0;Q->rear = 0;
}

2. 判空

int QueueEmpty(SqQueue* Q) {return Q->front == Q->rear;
}

3. 判满

int QueueFull(SqQueue* Q) {return (Q->rear + 1) % MaxSize == Q->front;
}

4. 入队

int EntreQueue(SqQueue* Q,ElemType value) {if (QueueFull(Q)){printf("队列已满,无法入队!\n");return -2;}Q->data[Q->rear] = value;Q->rear = (Q->rear + 1) % MaxSize;return 0;  //入队成功
}

5. 出队

int LeaveQueue(SqQueue* Q,ElemType* value) {if (QueueEmpty(Q)){printf("队列为空,无法有元素出队!\n");return -2;}*value = Q->data[Q->front];Q->front = (Q->front + 1) % MaxSize;return 0;  //出队成功
}

6. 打印

void printQueue(SqQueue* Q) {if (QueueEmpty(Q)){printf("队列为空,没有元素打印!\n");return;}int i = Q->front;printf("队列中的元素为:");while (i != Q->rear) {printf("%d ", Q->data[i]);i = (i + 1) % MaxSize;}printf("\n");
}

7. 注销

这里其实循环队列不需要特别的注销操作,只是为了保持接口统一

void destroyQueue(SqQueue* Q) {Q->front = 0;Q->rear = 0;
}

8. 测试

int main() {SqQueue Q;InitQueue(&Q);// 入队操作测试EntreQueue(&Q, 11);EntreQueue(&Q, 22);EntreQueue(&Q, 33);printQueue(&Q);  //队列中的元素为:11 22 33// 出队操作测试ElemType value;if (LeaveQueue(&Q,&value) == 0){printf("出队的元素是:%d\n", value);  // 出队的元素是:11}printQueue(&Q);  //队列中的元素为:22 33// 判空操作测试if (QueueEmpty(&Q)){printf("队列为空!\n");}else {printf("队列不为空!\n");  //队列不为空!}// 判满操作测试if (QueueFull(&Q)){printf("队列满了\n");}else {printf("队列还没满\n");  //队列还没满}// 注销队列destroyQueue(&Q);printQueue(&Q);  // 队列为空,没有元素打印!return 0;
}

9. 完整代码

#include<stdio.h>
#define MaxSize 50
typedef int ElemType;typedef struct SqQueue {ElemType data[MaxSize];  // 用数组存放队列元素int front;  // 队头指针.负责出队int rear;   //队尾指针,负责进队
}SqQueue;//操作1——初始化
void InitQueue(SqQueue* Q) {Q->front = 0;Q->rear = 0;
}//操作2——判空
int QueueEmpty(SqQueue* Q) {return Q->front == Q->rear;
}//操作3——判满
int QueueFull(SqQueue* Q) {return (Q->rear + 1) % MaxSize == Q->front;
}//操作4——入队
int EntreQueue(SqQueue* Q,ElemType value) {if (QueueFull(Q)){printf("队列已满,无法入队!\n");return -2;}Q->data[Q->rear] = value;Q->rear = (Q->rear + 1) % MaxSize;return 0;  //入队成功
}//操作5——出队
int LeaveQueue(SqQueue* Q,ElemType* value) {if (QueueEmpty(Q)){printf("队列为空,无法有元素出队!\n");return -2;}*value = Q->data[Q->front];Q->front = (Q->front + 1) % MaxSize;return 0;  //出队成功
}
//操作6——打印
void printQueue(SqQueue* Q) {if (QueueEmpty(Q)){printf("队列为空,没有元素打印!\n");return;}int i = Q->front;printf("队列中的元素为:");while (i != Q->rear) {printf("%d ", Q->data[i]);i = (i + 1) % MaxSize;}printf("\n");
}
//操作7——注销
// 这里其实循环队列不需要特别的注销操作,只是为了保持接口统一
void destroyQueue(SqQueue* Q) {Q->front = 0;Q->rear = 0;
}int main() {SqQueue Q;InitQueue(&Q);// 入队操作测试EntreQueue(&Q, 11);EntreQueue(&Q, 22);EntreQueue(&Q, 33);printQueue(&Q);  //队列中的元素为:11 22 33// 出队操作测试ElemType value;if (LeaveQueue(&Q,&value) == 0){printf("出队的元素是:%d\n", value);  // 出队的元素是:11}printQueue(&Q);  //队列中的元素为:22 33// 判空操作测试if (QueueEmpty(&Q)){printf("队列为空!\n");}else {printf("队列不为空!\n");  //队列不为空!}// 判满操作测试if (QueueFull(&Q)){printf("队列满了\n");}else {printf("队列还没满\n");  //队列还没满}// 注销队列destroyQueue(&Q);printQueue(&Q);  // 队列为空,没有元素打印!return 0;
}

10. 运行截图

 分享小妙招 :如果对哪个操作不是很明白,就询问AI:请结合以下代码详细描述XXX操作的过程 + 粘贴的代码

本人菜鸟一只,如果文章有出错处,欢迎评论区指正!


http://www.ppmy.cn/news/1578841.html

相关文章

【git】 贮藏 stash

贮藏是我在sourcetree上看到的名词。之前只是浅浅的用来收藏一下修改的文件&#xff0c;没有完整的使用过。今天有幸使用了一次就来展开说说。 使用原因就不赘述了&#xff0c;错误的操作少提为好&#xff0c;操作步骤如下&#xff1a; 查看贮藏列表git stash list #输出&…

机器学习(吴恩达)

一, 机器学习 机器学习定义: 计算机能够在没有明确的编程情况下学习 特征: 特征是描述样本的属性或变量&#xff0c;是模型用来学习和预测的基础。如: 房屋面积, 地理位置 标签: 监督学习中需要预测的目标变量&#xff0c;是模型的输出目标。如: 房屋价格 样本: 如: {面积100㎡…

OpenCV开发笔记(八十三):图像remap实现哈哈镜效果

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/146213444 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

Windows CMD 命令大全(综合开发整理版)

CMD Windows CMD 命令大全(综合整理版)基础操作与文件管理类系统维护与配置类网络与连接类开发者常用命令CMD 黑窗口使用技巧1. **效率操作**2. **高级功能**3. **开发者高效技巧**注意事项**微软官方文档****其他实用资源****如何高效使用官方文档**Windows CMD 命令大全(综…

云效、流水线、Gradle缓存问题、build.gradle配置snapshot

云效 大部分研发者们或许都听说过阿里云云效&#xff0c;甚至有不少使用经验&#xff1b;但是几乎很少有人会关注过云效的&#xff08;子&#xff09;域名&#xff1a; 如上图&#xff0c;云效的定位&#xff08;愿景&#xff09;就是为研发者们提供一站式的团队协作、效能提…

vscode自定义背景色

故事背景,vscode默认的是黑色&#xff0c;windows默认的是白色&#xff0c;白色看久了&#xff0c;看黑色看不清楚。以前写C灰色习惯了。需要修改背景色。 自定义背景色 打开 VSCode。 按下 Ctrl , 打开设置。 在搜索栏中输入 workbench.colorCustomizations。 点击 “编辑 i…

数字IC/FPGA校招笔试题解析(一)

数字IC/FPGA校招笔试题解析&#xff08;一&#xff09; 题目1 问题&#xff1a;数字电路设计中&#xff0c;下列哪种手段无法消除竞争冒险现象&#xff1f; 选项&#xff1a; a. 加滤波电容&#xff0c;消除毛刺 b. 增加冗余项消除逻辑冒险 c. 增加选通信号&#xff0c;避开毛…

纯前端全文检索的两种实现方案:ElasticLunr.js 和 libsearch

纯前端全文检索的两种实现方案&#xff1a;ElasticLunr.js 和 libsearch 在前端开发中&#xff0c;实现全文检索功能可以显著提升用户体验&#xff0c;尤其是在处理大量文本数据时。本文将介绍两种流行的纯前端全文检索方案&#xff1a;ElasticLunr.js 和 libsearch。这两种方…