环形缓冲区 Ring Buffer 的实现

这篇具有很好参考价值的文章主要介绍了环形缓冲区 Ring Buffer 的实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

环形缓冲区(Circular Buffer 或 Ring Buffer)是一种数据结构,它在逻辑上形成一个闭环。这种结构非常适用于需要固定大小的缓冲区的情况,如音频处理、网络通信、实时数据传输等。环形缓冲区的主要特点和用途包括:

固定大小:环形缓冲区的大小在创建时确定,并且在其生命周期内保持不变。

高效的数据插入和移除:在环形缓冲区中添加或移除元素(通常是在头部添加,在尾部移除)是非常高效的,因为这些操作不需要移动缓冲区中的其他元素。

循环覆盖:当缓冲区填满时,新添加的元素将覆盖最早添加的元素。这使得环形缓冲区非常适用于处理流式数据,其中只关心最近的数据。

无需动态内存分配:由于环形缓冲区的大小是固定的,因此在初始化后不需要额外的内存分配。

下面是C#中一个泛型环形缓冲区的实现文章来源地址https://www.toymoban.com/news/detail-747862.html

// LiteRingBuffer 是一个泛型类,用于存储类型为 T 的数据
public class LiteRingBuffer<T> : IEnumerable<T>
{

    // _elements 数组用于存储环形缓冲区的元素
    private readonly T[] _elements;

    // _start 和 _end 分别表示缓冲区中第一个和最后一个元素的索引
    private int _start;
    private int _end;

    // _count 表示缓冲区中当前元素的数量
    private int _count;

    // _capacity 表示缓冲区的最大容量
    private readonly int _capacity;
    
    // 索引器,用于访问缓冲区中的元素。它将索引 i 映射到环形缓冲区的正确位置
    public T this[int i] => _elements[(_start + i) % _capacity];

    // 构造函数,初始化环形缓冲区的大小
    public LiteRingBuffer(int count)
    {
        _elements = new T[count];
        _capacity = count;
    }

    // Add 方法用于向缓冲区添加新元素
    public void Add(T element)
    {
        if(_count == _capacity)
            throw new ArgumentException(); // 如果缓冲区已满,则抛出异常
        _elements[_end] = element; // 将元素添加到_end指向的位置
        _end = (_end + 1) % _capacity; // 更新_end索引
        _count++; // 增加元素数量
    }

    // FastClear 方法用于快速清空缓冲区
    public void FastClear()
    {
        _start = 0;
        _end = 0;
        _count = 0;
    }

    // Count 属性返回缓冲区中的元素数量
    public int Count => _count;

    // First 属性返回缓冲区中的第一个元素
    public T First => _elements[_start];

    // Last 属性返回缓冲区中的最后一个元素
    public T Last => _elements[(_start+_count-1)%_capacity];

    // IsFull 属性指示缓冲区是否已满
    public bool IsFull => _count == _capacity;

    // RemoveFromStart 方法从缓冲区的开始移除指定数量的元素
    public void RemoveFromStart(int count)
    {
        if(count > _capacity || count > _count)
            throw new ArgumentException(); // 如果请求移除的元素数量不合法,则抛出异常
        _start = (_start + count) % _capacity; // 更新_start索引
        _count -= count; // 减少元素数量
    }

    // GetEnumerator 方法提供了遍历缓冲区的方法
    public IEnumerator<T> GetEnumerator()
    {
        int counter = _start;
        while (counter != _end)
        {
            yield return _elements[counter];
            counter = (counter + 1) % _capacity;
        }           
    }

    // IEnumerable 接口的实现,用于集合的迭代
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

到了这里,关于环形缓冲区 Ring Buffer 的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【STM32 CubeMX】学STM必会的数据结构——环形缓冲区

    在嵌入式系统开发中,经常需要处理数据的缓存和传输,而环形缓冲区是一种常见且有效的数据结构,特别适用于处理实时数据流或者在有限的内存资源下高效地管理数据。在STM32微控制器的开发中,使用CubeMX工具可以方便地配置和生成环形缓冲区的代码,从而加速开发过程

    2024年04月12日
    浏览(21)
  • 【Linux】模拟实现FILE以及认识缓冲区

    刷新缓冲逻辑图 自定义实现 如何强制刷新内核缓冲区 根据文件描述符进行强制刷新 例子 像我们进行scanf输入的时候,其实本身我们输入的是一串字符串,将这个字符串读入对应的缓冲区buff后,然后通过分解工作,进一步传入系统,系统,系统在通过一些指令输入输出想要

    2024年02月10日
    浏览(34)
  • 【LeetCode】模拟实现FILE以及认识缓冲区

    刷新缓冲逻辑图 自定义实现 如何强制刷新内核缓冲区 根据文件描述符进行强制刷新 例子 像我们进行scanf输入的时候,其实本身我们输入的是一串字符串,将这个字符串读入对应的缓冲区buff后,然后通过分解工作,进一步传入系统,系统,系统在通过一些指令输入输出想要

    2024年02月11日
    浏览(34)
  • linuxC语言缓冲区及小程序的实现

    为缓和 CPU 与 I/O 设备之间速度不匹配,文件缓冲区用以暂时存放读写期间的文件数据而在内存区预留的一定空间。使用文件缓冲区可减少读取硬盘的次数。 系统自动地在内存为程序中每一个正在使用的文件开辟一块文件缓冲区。 从内存向磁盘输出数据,先送到内存中的缓冲

    2024年02月04日
    浏览(29)
  • 【Linux】语言层面缓冲区的刷新问题以及简易模拟实现

    我们接下来要谈论的是我们语言层面的缓冲区(C,C++之类的),不是我们操作系统内核里面自带的缓冲区,我们每次在打开一个文件的时候,以C语言为例子, C语言会为我们所打开的这个文件分配一块缓冲区,用来缓存我们读写的数据`,这个缓冲区会被放在我们创建的FILE的

    2024年02月05日
    浏览(38)
  • Linux文件系列: 深入理解缓冲区和C标准库的简单模拟实现

    至此,我们理解了缓冲区的概念和作用,下面我们来简易模拟实现一下C标准库 我们要实现的是: 1.文件结构体的定义 1.首先要有一个文件结构体: 刷新策略分别宏定义为 2.myfopen等等函数的声明 path:文件路径+文件名 mode:打开文件的方式 “r”:只读 “w”:覆盖写 “a”:追加写 strea

    2024年03月11日
    浏览(56)
  • 【看表情包学Linux】缓冲区的概念 | Git 三板斧 | 实现简易进度条

       爆笑教程,只送有缘人  👉 《看表情包学Linux》 💭 写在前面: 本章我们先对缓冲区的概念进行一个详细的探究,之后会带着大家一步步去编写一个简陋的 \\\"进度条\\\" 小程序,过程还是挺有意思的,虽然实现的过程表现得非常沙雕,但它是本 Linux 专栏中第一个小程序。

    2024年02月02日
    浏览(42)
  • Java中使用JTS实现WKT字符串读取转换线、查找LineString的list中距离最近的线、LineString做缓冲区扩展并计算点在缓冲区内的方位角

    Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等): Java中使用JTS对空间几何计算(读取WKT、距离、点在面内、长度、面积、相交等)_jts-core_霸道流氓气质的博客-CSDN博客 Java+GeoTools实现WKT数据根据EPSG编码进行坐标系转换: Java+GeoTools实现WKT数据根据

    2024年02月09日
    浏览(32)
  • 理解缓冲区

    对于这样的代码,首先可以肯定的是 printf 语句先于 sleep 执行,既然如此那么就应该是先打印语句然后进行休眠,下面看看结果: 但这里却是先休眠以后再打印语句,这是因为存在一个叫缓冲区的东西,当我们要向外设写入数据(让显示器显示就是向显示器写入数据)时会将

    2023年04月25日
    浏览(63)
  • 8.缓冲区管理

    双缓冲区:TC+M 假设初始状态缓冲区1满,缓冲区2空,工作区为空。 刚开始缓冲区2为空,所以设备可以向缓冲区2中冲入数据耗时T,另一方面刚开始缓冲区1中是满的,所以刚开始就可以把缓冲区1中的数据传送到工作区中,M时刻工作区被充满,CPU就开始处理数据耗时C,处理完

    2024年02月11日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包