C语言,环形队列

什么是环形队列?

环形缓冲区是一个非常典型的数据结构,这种数据结构符合生产者,消费者模型,可以理解它是一个水坑,生产者不断的往里面灌水,消费者就不断的从里面取出水。

640?wx_fmt=png

那就可能会有人问,既然需要灌水,又需要取出水,为什么还需要开辟一个缓冲区内存空间呢?直接把生产者水管的尾部接到消费者水管的头部不就好了,这样可以省空间啊。

640?wx_fmt=png

答案是不行的,生产者生产水的速度是不知道的,消费者消费水的速度也是不知道的,如果你强制接在一起,因为生产和消费的速度不同,就非常可能存在水管爆炸的情况,你说这样危险不危险?

640?wx_fmt=png

在音频系统框架下,alsa就是使用环形队列的,在生产者和消费者速度不匹配的时候,就会出现xrun的问题。

环形队列的特点

1、数组构造环形缓冲区

假设我们用数组来构造一个环形缓存区,如下图

640?wx_fmt=png

我们需要几个东西来形容这个环形缓冲区,一个的读位置,一个是写位置,一个是环形缓冲区的长度

640?wx_fmt=png

从图片看,我们知道,这个环形缓冲区的读写位置是指向数组的首地址的,环形缓冲区的长度是 5 。

那如何判断环形缓冲区为空呢?

如果 R == W  就是读写位置相同,则这个环形缓冲区为空

那如何判断环形缓冲区满了呢?

如果 (W - R )= Len ,则这个环形缓冲区已经满了。

2、向环形缓冲区写入 3个数据

640?wx_fmt=png

写入 3 个数据后,W 的值等于 3 了,R 还是等于 0。

3个企鹅已经排列

3、从环形缓冲区读取2个数据

640?wx_fmt=png

读出两个数据后,R = 2 了,这个时候,W还是等于 3,毕竟没有再写过数据了。

4、再写入3个数据

640?wx_fmt=png

如果 W > LEN 后,怎么找到最开始的位置的呢?这个就需要进行运算了,W%LEN 的位置就是放入数据的位置 ,6%5 = 1。

5、再写入1个数据

640?wx_fmt=png

这个时候环形队列已经满了,要是想再写入数据的话,就不行了,(W - R) = 5 == LEN

代码实现

/* 实现的最简单的ringbuff 有更多提升空间,可以留言说明 */
#include "stdio.h"
#include "stdlib.h"#define LEN 10/*环形队列结构体*/
typedef struct ring_buff{int array[LEN];int W;int R;
}*ring;/*环形队列初始化*/
struct ring_buff * fifo_init(void)
{struct ring_buff * p = NULL;p = (struct ring_buff *)malloc(sizeof(struct ring_buff));if(p == NULL){printf("fifo_init malloc error\n");return NULL;}p->W = 0;p->R = 0;return p;
}/*判断环形队列是否已经满了*/
int get_ring_buff_fullstate(struct ring_buff * p_ring_buff)
{/*如果写位置减去读位置等于队列长度,就说明这个环形队列已经满*/if((p_ring_buff->W - p_ring_buff->R) == LEN){return (1);}else{return (0);}
}/*判断环形队列为空*/
int get_ring_buff_emptystate(struct ring_buff * p_ring_buff)
{/*如果写位置和读的位置相等,就说明这个环形队列为空*/if(p_ring_buff->W == p_ring_buff->R){return (1);}else{return (0);}
}
/*插入数据*/
int ring_buff_insert(struct ring_buff * p_ring_buff,int data)
{if(p_ring_buff == NULL){printf("p null\n");return (-1);	}if(get_ring_buff_fullstate(p_ring_buff) == 1){printf("buff is full\n");return (-2);}p_ring_buff->array[p_ring_buff->W%LEN] = data;p_ring_buff->W ++;//printf("inset:%d %d\n",data,p_ring_buff->W);return (0);
}/*读取环形队列数据*/
int ring_buff_get(struct ring_buff * p_ring_buff)
{int data = 0;if(p_ring_buff == NULL){printf("p null\n");return (-1);	}if(get_ring_buff_emptystate(p_ring_buff) == 1){printf("buff is empty\n");return (-2);}data = p_ring_buff->array[p_ring_buff->R%LEN];p_ring_buff->R++;return data;
}/*销毁*/
int ring_buff_destory(struct ring_buff * p_ring_buff)
{if(p_ring_buff == NULL){printf("p null\n");return (-1);	}free(p_ring_buff);return (0);
}int main()
{int i = 0;/*定义一个环形缓冲区*/ring pt_ring_buff = fifo_init();/*向环形缓冲区中写入数据*/for(i = 0;i<10;i++){ring_buff_insert(pt_ring_buff,i);}/*从环形缓冲区中读出数据*/for(i = 0;i<10;i++){printf("%d ",ring_buff_get(pt_ring_buff));}/*销毁一个环形缓冲区*/ring_buff_destory(pt_ring_buff);return (1);
}

640?wx_fmt=png

换一个写法,这个写法是各种大神级别的


/* 实现的最简单的ringbuff 有更多提升空间,可以留言说明 */
#include "stdio.h"
#include "stdlib.h"#define LEN 64/*环形队列结构体*/
typedef struct ring_buff{int array[LEN];int W;int R;
}*ring;/*环形队列初始化*/
struct ring_buff * fifo_init(void)
{struct ring_buff * p = NULL;p = (struct ring_buff *)malloc(sizeof(struct ring_buff));if(p == NULL){printf("fifo_init malloc error\n");return NULL;}p->W = 0;p->R = 0;return p;
}/*判断环形队列是否已经满了*/
int get_ring_buff_fullstate(struct ring_buff * p_ring_buff)
{/*如果写位置减去读位置等于队列长度,就说明这个环形队列已经满*/if((p_ring_buff->W - p_ring_buff->R) == LEN){return (1);}else{return (0);}
}/*判断环形队列为空*/
int get_ring_buff_emptystate(struct ring_buff * p_ring_buff)
{/*如果写位置和读的位置相等,就说明这个环形队列为空*/if(p_ring_buff->W == p_ring_buff->R){return (1);}else{return (0);}
}
/*插入数据*/
int ring_buff_insert(struct ring_buff * p_ring_buff,int data)
{if(p_ring_buff == NULL){printf("p null\n");return (-1);	}if(get_ring_buff_fullstate(p_ring_buff) == 1){printf("buff is full\n");return (-2);}//p_ring_buff->array[p_ring_buff->W%LEN] = data;p_ring_buff->array[p_ring_buff->W&(LEN -1)] = data;	p_ring_buff->W ++;//printf("inset:%d %d\n",data,p_ring_buff->W);return (0);
}/*读取环形队列数据*/
int ring_buff_get(struct ring_buff * p_ring_buff)
{int data = 0;if(p_ring_buff == NULL){printf("p null\n");return (-1);	}if(get_ring_buff_emptystate(p_ring_buff) == 1){printf("buff is empty\n");return (-2);}//data = p_ring_buff->array[p_ring_buff->R%LEN];data = p_ring_buff->array[p_ring_buff->R&(LEN -1)];p_ring_buff->R++;return data;
}/*销毁*/
int ring_buff_destory(struct ring_buff * p_ring_buff)
{if(p_ring_buff == NULL){printf("p null\n");return (-1);	}free(p_ring_buff);return (0);
}int main()
{int i = 0;/*定义一个环形缓冲区*/ring pt_ring_buff = fifo_init();/*向环形缓冲区中写入数据*/for(i = 0;i<10;i++){ring_buff_insert(pt_ring_buff,i);}/*从环形缓冲区中读出数据*/for(i = 0;i<10;i++){printf("%d ",ring_buff_get(pt_ring_buff));}/*销毁一个环形缓冲区*/ring_buff_destory(pt_ring_buff);return (1);
}

总结

环形队列的使用场景非常多,安卓的音频数据读写,很多都用到环形队列,我们在开发过程中使用的环形队列肯定比我上面的那个例子要复杂的多,我这里演示的是比较简单的功能,但是麻雀虽小,五脏俱全,希望这个麻雀让你们了解这个数据结构。在实际项目中大展身手。

—————END—————

640?wx_fmt=jpeg
扫码或长按关注
回复「 加群」进入技术群聊

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

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

相关文章

php print r用法,php中echo(),print(),print_r()用法

从我对echo(),print(),print_r()这个函数的理解是echo可输入字符串变量常量&#xff0c;print与echo差不多,但print_r可以打印数组而前两者是不可以的,下面我来详细介绍它们三个的用法与区别吧。echo是PHP语句,print和print_r是函数,语句没有返回值,函数可以有返回值(即便没有用…

音频几个重要的参数

音频的采样率是什么&#xff1f;如果把音频当成一条曲线&#xff0c;那么采样率就是一秒钟从这个曲线里面提取样本的次数。8,000 Hz - 电话所用采样率, 对于人的说话已经足够11,025 Hz - AM调幅广播所用采样率22,050 Hz和24,000 Hz - FM调频广播所用采样率32,000 Hz - miniDV 数…

servlet中web.xml配置详解

Web.xml常用元素 <web-app> <display-name></display-name> 定义了WEB应用的名字 <description></description> 声明WEB应用的描述信息 <context-param></context-param> context-param元素声明应用范围内的初始化参数。 <fi…

ps绿化工具_绿化消防车价位

绿化消防车价位绿化消防车价位 4吨东风消防洒水车&#xff0c;又称为多功能消防车&#xff0c;它是在东风原装二类底盘基础上加消防泵、消防炮、洒水炮及洒水车的前冲后洒、侧喷及水罐体组成&#xff0c;既能参加救火灭火功能&#xff0c;水炮的有效射程≥45米&#xff0c;每秒…

oracle基本的查询语句,Oracle基本查询语句

书写一个最简单的 sql 语句&#xff0c;查询一张表的所有行和所有列&#xff1a;该实验的目的是初步认识 sql 语句,执行一个最简单的查询.Select * from emp;EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO----- ---------- --------- ---------- ------------ ---------- ----…

今天星期六

突然之间就到周六了&#xff0c;我记得上周的时候&#xff0c;我一个朋友说&#xff0c;这周我们要开个课程&#xff0c;课程的名字就叫做&#xff0c;「如何让你拥有快乐的今天」&#xff0c;然而&#xff0c;上周已经过去&#xff0c;嗖的一声&#xff0c;已经到了这周了&…

python异常捕获_python 捕获异常

异常&#xff1a;由于代码的逻辑或者语法错误导致的程序中断。 在学习Python的过程当中&#xff0c;大家一定要区分清楚异常和布尔值False 布尔值的False只是一个值&#xff0c;通常代表的是一个条件的不成立&#xff0c;常用于逻辑判断 比如&#xff1a; 1 num 2 2 print(num…

4、requests-基础

1、发出一个get请求&#xff1a; r requests.get(https://github.com/timeline.json) 返回给我们的r&#xff0c;是一个requets的对象&#xff0c;这个requests的对象中我们可以调用一些属性&#xff0c;方便我们得到更加详细的信息&#xff1b; r.status_code # 响应状…

C语言验证大小端的几个方法

大小端的问题在很多面试笔试中都会遇到&#xff0c;最直接的考察是&#xff0c;笔试的时候&#xff0c;让你写一个代码&#xff0c;如何确定当前系统是大端还是小端的。什么是大端和小端呢&#xff1f;大端&#xff1a; 高位字节排放在内存的低地址端&#xff0c;低位字节排放在…

python中import os_Python常用模块os--与操作系统交互

os.getcwd() 返回当前工作目录绝对路径 Python 3.7.0 (v3.7.0:1bf9cc5093, Jun 27 2018, 04:59:51) [MSC v.1914 64 bit (AMD64)] on win32 Type "copyright", "credits" or "license()" for more information. >>> import os >>…

Windows系统带你一步一步无脑使用babel

不废话直接写看步骤&#xff1a; 1、在F盘新建一个文件夹叫babel 2、npm init 初始化项目 3、全局安装npm install babel babel-cli -g 4、项目安装npm install babel-cli --save-dev 项目目录里会多一个node_modules包 5、新建一个es6.js文件 随便写一段es6 6、输入指令babel …

php处理base64数据,php基于base64解码数据与图片的转换

header(Content-type:text/html;charsetutf-8);//读取图片文件&#xff0c;转换成base64编码格式$image_file ./4296762_165319032930_2.jpg;$image_info getimagesize($image_file);// $image_info /9j/4AAQSkZJRgABAQAASABIAAD......;$base64_image_content "data:{…

python sklearn 归一化_数据分析|Python特征工程(5)

OX00 引言数据和特征决定了机器学习的上限&#xff0c;而模型和算法只是逼近这个上限而已。由此可见&#xff0c;特征工程在机器学习中占有相当重要的地位。在实际应用当中&#xff0c;可以说特征工程是机器学习成功的关键。特征做不好&#xff0c;调参调到老。重视调参&#x…

盘点多款国产Linux桌面操作系统

编辑&#xff1a;strongerHuang微信公众号&#xff1a;strongerHuang素材来源&#xff1a;百度百科、网络国产操作系统多为以Linux 为基础二次开发的操作系统。2014年4月8日起&#xff0c;美国微软公司停止了对Windows XP SP3操作系统提供服务支持&#xff0c;这引起了社会和广…

include包含头文件的语句中,双引号和尖括号的区别

include包含头文件的语句中,双引号和尖括号的区别 #include <>格式&#xff1a;引用标准库头文件&#xff0c;编译器从标准库目录开始搜索 #incluce ""格式&#xff1a;引用非标准库的头文件&#xff0c;编译器从用户的工作目录开始搜索预处理器发现 #include …

Oracle订单号就是授权号码,oracle多单号的说明

在ORACLE中&#xff0c;单引号有两个作用&#xff0c;一是字符串是由单引号引用&#xff0c;二是转义。单引号的使用是就近配对&#xff0c;即就近原则。而在单引号充当转义角色时相对不好理解1、从第二个单引号开始被视为转义符&#xff0c;如果第二个单引号后面还有单引号(哪…

kafka rabbitmq优劣对比_Kafka、RabbitMQ、RocketMQ等消息中间件的对比

原文链接&#xff1a;Kafka、RabbitMQ、RocketMQ等消息中间件的对比消息中间件现在有不少&#xff0c;网上很多文章都对其做过对比&#xff0c;在这我对其做进一步总结与整理。RocketMQ淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件&#xff0c;使用Mysql作为消息存…

网络负载平衡oracle,[Oracle] RAC 之 - 负载均衡深入解析

Oracle RAC提供两种方式实现负载均衡&#xff0c;第一种是纯技术手段&#xff0c;即在用户连接时&#xff0c;根据系统当前的负载情况决定由哪个节点处理用户请求&#xff1b;第二种是面向业务&#xff0c;人为的把应用切分成很多service&#xff0c;通过某个service过来的连接…

你应该知道这些有意思的代码

Kyle McCormick 在 StackExchange 上发起了一个叫做 Tweetable Mathematical Art 的比赛&#xff0c;参赛者需要用三条推这么长的代码来生成一张图片。具体地说&#xff0c;参赛者需要用 C 语言编写 RD 、 GR 、 BL 三个函数&#xff0c;每个函数都不能超过 140 个字符。每个函…

parachute

actuality /ˌktʃuˈləti/ Jane thinks that they will probably marry in actuality but that he can not love the vain, shallow woman. /ˈwʊmən/ vain men can be jsut as vain as women /ˈwɪmɪn/ 男人有时和女人一样虚荣 The instructor struggled vainly to …