【数据结构(C语言描述)】环形队列

article/2025/9/28 2:38:54

目录

  • 一、基础知识
  • 二、数组实现环队
    • 2.1 初始化
    • 2.2 判断环队是否为空
    • 2.3 判断环队是否为满
    • 2.4 入队
    • 2.5 出队
    • 2.6 取队头元素
    • 2.7 取队尾元素
    • 2.8 销毁环队
  • 三、链表实现环队
    • 3.1 初始化
    • 3.2 判断环队是否为空
    • 3.3 判断环队是否为满
    • 3.4 入队
    • 3.5 出队
    • 3.6 取队头元素
    • 3.7 取队尾元素
    • 3.8 销毁环队


一、基础知识

  • 环形队列:是首尾相连的先进后出的数据结构

  • 特点:给定空间大小

  • 应用:环形队列广泛用于网络数据收发,和不同程序间数据交换(比如内核与应用程序大量交换数据,从硬件接收大量数据)

  • 实现:① 数组环队 ② 链表环队
    - 在这里插入图片描述

  • 一个严重的问题
    (1) 如何判断队为空?(2) 如何判断队为满?答案:(1)front == tail (2)front == tail
    为了区别两个判断条件的重合问题,需要在数组队/链队预留一个空间的位置
    (1) front == tail (2) (tail+1)%5 == front
    在这里插入图片描述

二、数组实现环队

结构体

typedef struct CircularQueue
{int* arry; int front;int tail;int size;//数组大小
}CQueue;

2.1 初始化

//初始化
void CQueueInit(CQueue* cq, int k)
{assert(cq);cq->arry = (int*)malloc(sizeof(int) * (k+1));cq->front = cq->tail = 0;cq->size = k;
}

2.2 判断环队是否为空

//判断环形队列是否为空
bool CQueueIsEmpty(CQueue* cq)
{assert(cq);return cq->front == cq->tail;
}

2.3 判断环队是否为满

//判断环形队列是否为满
bool CQueueIsFull(CQueue* cq)
{assert(cq);return (cq->tail + 1) % (cq->size + 1) == cq->front;
}

2.4 入队

//入队
void CQueuePush(CQueue* cq, int x)
{assert(cq);if (CQueueIsFull(cq)){printf("队满!");exit(0);}cq->arry[cq->tail] = x;//赋值cq->tail = (cq->tail + 1) % (cq->size + 1);//tail走一步
}

2.5 出队

//出队
void CQueuePop(CQueue* cq)
{assert(cq);if (CQueueIsEmpty(cq)){printf("队空!");exit(0);}cq->front = (cq->front + 1) % (cq->size + 1);//front走一步
}

2.6 取队头元素

//取队头元素
int CQueueFront(CQueue* cq)
{assert(cq);if (CQueueIsEmpty(cq)){printf("队空!");exit(0);}return cq->arry[cq->front];
}

2.7 取队尾元素

//取队尾元素
int CQueueBack(CQueue* cq)
{assert(cq);if (CQueueIsEmpty(cq)){printf("队空!");exit(0);}int tail_i = (cq->tail + cq->size) % (cq->size + 1);//找到tail的上一个位置return cq->arry[tail_i];
}

2.8 销毁环队

//环形队列的销毁
void CQueueDestroy(CQueue* cq)
{assert(cq);free(cq->arry);free(cq);
}

“向后走”(cur+1)%(k+1)
“向前走”(cur+k)%(k+1)

三、链表实现环队

结构体

typedef int DataType;
typedef struct CQueueNode
{DataType data;CQueueNode* next;
}CQueueNode;
typedef struct CQueue
{CQueueNode* front;CQueueNode* tail;
}CQueue;

3.1 初始化

//初始化
void CQueueInit(CQueue* cq, int k)
{assert(cq);CQueueNode* plist = CreatCQueueList(k + 1);cq->front = cq->tail = plist;
}
//创建k个结点的链表
CQueueNode* CreatCQueueList(int k)
{CQueueNode* phead = NULL;CQueueNode* tail = phead;while (k){CQueueNode* newNode = (CQueueNode*)malloc(sizeof(CQueueNode));newNode->next = NULL;if (phead == NULL){phead = tail =newNode;}else{tail->next = newNode;tail = newNode;}--k;}tail->next = phead;return phead;
}

3.2 判断环队是否为空

//判断环形队列是否为空
bool CQueueIsEmpty(CQueue* cq)
{assert(cq);return cq->front == cq->tail;
}

3.3 判断环队是否为满

//判断环形队列是否为满
bool CQueueIsFull(CQueue* cq)
{assert(cq);return cq->front == cq->tail->next;
}

3.4 入队

//入队
void CQueuePush(CQueue* cq, int x)
{assert(cq);if (CQueueIsFull(cq)){printf("队满!");exit(0);}cq->tail->data = x;cq->tail = cq->tail->next;
}

3.5 出队

//出队
void CQueuePop(CQueue* cq)
{assert(cq);if (CQueueIsEmpty(cq)){printf("队空!");exit(0);}cq->front = cq->front->next;
}

3.6 取队头元素

//取队头元素
int CQueueFront(CQueue* cq)
{assert(cq);if (CQueueIsEmpty(cq)){printf("队空!");exit(0);}return cq->front->data;
}

3.7 取队尾元素

//取队尾元素
int CQueueBack(CQueue* cq)
{assert(cq);if (CQueueIsEmpty(cq)){printf("队空!");exit(0);}CQueueNode* cur = cq->front;while (cur){if (cur->next == cq->tail)break;cur = cur->next;}return cur->data;
}

3.8 销毁环队

//环形队列的销毁
void CQueueDestroy(CQueue* cq)
{assert(cq);//第一层:free链表结点CQueueNode* cur = cq->front;while (cur){CQueueNode* next = cur->next;free(cur);cur = next;}//第二层:free front和tailfree(cq);
}

http://chatgpt.dhexx.cn/article/wqP2ftws.shtml

相关文章

环形队列原理,全网最通俗易懂

队列是什么 队列是一种很常见的数据结构,满足先进先出的方式,如果我们设定队列的最大长度,那就意味着进队列和出队列的元素的数量实则满足一种动态平衡。 如果我们把首次添加入队列的元素作为一个一维坐标的原点,那么随着队列中…

Mysql 死锁和死锁的解决方案

最近在研究Mysql底层原理,研究到了死锁,感觉挺有意思,在这里和大家分享一下 前置知识:需要了解锁的种类,如表锁、行锁;行锁又分为记录锁、间隙锁、临键锁等等;什么情况下会加表锁,什…

mysql死锁演示

背景: 线上日志突然爆了有数据库死锁的日志。 通过以下语句查询数据库死锁的日志 SHOW ENGINE INNODB STATUS 通过 日志分析,看到了两条update语句并且是里面有子查询。还有两个表的更新顺序问题。 解决方案是:加了分布式锁,…

记录一次mysql死锁

一,死锁发现 项目中有一个接口包含更新操作1,后面发现更新失败,通过查看应用程序日志,发现发生了死锁 sql 1 如下 1.最初版本根据id为条件,更新(plan_start_time 二级索引) update tt_task …

深入MySQL死锁场景

总结死锁需满足以下条件: 2个或者2个以上的并发事务操作并发事务之间存在锁冲突锁冲突关系成环形 GAP锁和Insert的隐式锁,最容易导致死锁,以下分析从这俩典型场景开始。 1. 表结构 建立以下表作为场景验证,id为主键&#xff0…

mysql死锁查询语句

mysql 死锁:如何解决mysql死锁 可直接在mysql命令行执行:showengineinnodbstatus\G;查看造成死锁的sql语句,分析索引情况,然后优化sql然后showprocesslist;另外可以打开慢查询日志,linux下打开需在my.cnf的[mysqld]里面加上以下内…

MySQL死锁排查步骤

系列文章目录 第一章:sql_mode模式 第二章:optimize table、analyze table、alter table、gh-ost 第三章:InnoDB MVCC原理 第四章:sql语句执行过程 第五章:Percona Toolkit工具简介 第六章:MySQL索引 第七…

MySql死锁过程

死锁一般怎么导致呢, 抛开一堆概念, 我就把死锁当成死结。 就是你代码获取锁的顺序问题。 MySql的死锁和我们正常代码也一样, 都是互通的, 当你修改一个表的行数据的时候, 就需要对那一行数据进行加锁。 所以很容易想…

中秋遇到mysql死锁怎么办

文章目录 前言一、什么是死锁二、死锁的产生条件三、死锁示例四、死锁的分析和查看1.查看最近1个死锁信息2.查看正在运行中的事务信息3.查看加锁信息 五、死锁的内部处理方案1.死锁探测机制2.锁等待超时机制 六、手动释放锁1.表级锁手动释放2.行级锁手动释放 七、死锁的优化策略…

mysql 死锁分析

一、 什么是死锁 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等的进程称为死锁进程.二、 死锁产生的四个必要条件 1.互斥条件:指进…

MySQL死锁分析

背景知识 MySQL数据库InnoDB引擎的行级锁在使用时是在索引记录上加锁的。 行级锁从占有模式上分为: 排他锁:独占行数据,如某事务获取了该行记录的排他锁,其他事务在获取该记录的排他锁和共享锁时需等待;共享锁&…

故障分析 | MySQL死锁案例分析

作者:杨奇龙 网名“北在南方”,资深 DBA,主要负责数据库架构设计和运维平台开发工作,擅长数据库性能调优、故障诊断。 本文来源:原创投稿 *爱可生开源社区出品,原创内容未经授权不得随意使用,转…

MySQL死锁

参考博客: https://blog.csdn.net/sinat_41653656/article/details/109629094 Mysql 锁类型和加锁分析 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大&#xff…

mysql死锁语句_Mysql死锁

笔者最近在生产环境错误日志上看到updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction 这样的日志 ,网上看了很多文章 发现这篇文章 跟自己的场景非常接近…

【MySQL锁篇】MySQL死锁问题以及解决方案

目录 一、MySQL出现死锁的场景 二、MySQL当中的死锁现象 三、Insert语句怎样加锁的 隐式锁&显示锁 记录之间加有间隙锁 遇到唯一键冲突或者主键冲突的时候加锁 如果主键索引重复: ​​​​​​如果唯一二级索引重复: 四、如何避免MySQL当中的死锁现象 方案…

mysql死锁介绍以及解决

什么是死锁 死锁是2个线程在执行过程中, 因争夺资源而造成的相互等待的现象,若无外力作用,它们将无法推进下去。 死锁产生的4个必要条件 互斥条件 指进程对所分配的资源进行排他性使用,即一段时间内某资源只有一个进程占用&#…

MySQL - 死锁的产生及解决方案

MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件1.1 什么是死锁1.2 死锁产生的4个必要条件 2. 死锁案例2.1 表锁死锁2.2 行锁死锁2.3 共享锁转换为排他锁 3. 死锁排查4. 实例分析4.1 案例描述4.2 案例死锁问题复现4.3 死锁排查4.4 解决死锁 5. 如何避免死锁 1. …

MySql 死锁

MySql 死锁 一、什么是死锁InnoDB存储引擎定义了四种类型的行锁隔离等级对加锁的影响当前数据对加锁的影响 二、为什么会形成死锁两阶段锁协议产生死锁的四个必要条件 三、MySQL 如何处理死锁?杀死进程MySQL表间隙锁排他锁共享锁分析行锁定行锁优化 四、如何避免发生…

论文阅读|SMPL2015

摘要: 我们提出了一个学习过的人体形状和姿势相关的形状变化模型,该模型比以前更准确建模并与现有的图形管线兼容。我们的蒙皮多人线性模型(SMPL)是基于蒙皮顶点的模型,可以准确地表示各种各样的人体姿态。模型的参数是…

densepose与SMPL之IUV坐标转XYZ坐标

具体流程 一、SMPL模型 SMPL模型拥有6890个XYZ坐标的3D人体点,目前第一步需要将这6890个人体点进行分析,并将不同部位的点位进行归并,具体分为以下几个部分:头部,胸部,腰部,左臂,右…