翼度科技»论坛 编程开发 .net 查看内容

环形缓冲区 Ring Buffer 的实现

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
环形缓冲区(Circular Buffer 或 Ring Buffer)是一种数据结构,它在逻辑上形成一个闭环。这种结构非常适用于需要固定大小的缓冲区的情况,如音频处理、网络通信、实时数据传输等。环形缓冲区的主要特点和用途包括:
固定大小:环形缓冲区的大小在创建时确定,并且在其生命周期内保持不变。
高效的数据插入和移除:在环形缓冲区中添加或移除元素(通常是在头部添加,在尾部移除)是非常高效的,因为这些操作不需要移动缓冲区中的其他元素。
循环覆盖:当缓冲区填满时,新添加的元素将覆盖最早添加的元素。这使得环形缓冲区非常适用于处理流式数据,其中只关心最近的数据。
无需动态内存分配:由于环形缓冲区的大小是固定的,因此在初始化后不需要额外的内存分配。
下面是C#中一个泛型环形缓冲区的实现
  1. // LiteRingBuffer 是一个泛型类,用于存储类型为 T 的数据
  2. public class LiteRingBuffer<T> : IEnumerable<T>
  3. {
  4.     // _elements 数组用于存储环形缓冲区的元素
  5.     private readonly T[] _elements;
  6.     // _start 和 _end 分别表示缓冲区中第一个和最后一个元素的索引
  7.     private int _start;
  8.     private int _end;
  9.     // _count 表示缓冲区中当前元素的数量
  10.     private int _count;
  11.     // _capacity 表示缓冲区的最大容量
  12.     private readonly int _capacity;
  13.    
  14.     // 索引器,用于访问缓冲区中的元素。它将索引 i 映射到环形缓冲区的正确位置
  15.     public T this[int i] => _elements[(_start + i) % _capacity];
  16.     // 构造函数,初始化环形缓冲区的大小
  17.     public LiteRingBuffer(int count)
  18.     {
  19.         _elements = new T[count];
  20.         _capacity = count;
  21.     }
  22.     // Add 方法用于向缓冲区添加新元素
  23.     public void Add(T element)
  24.     {
  25.         if(_count == _capacity)
  26.             throw new ArgumentException(); // 如果缓冲区已满,则抛出异常
  27.         _elements[_end] = element; // 将元素添加到_end指向的位置
  28.         _end = (_end + 1) % _capacity; // 更新_end索引
  29.         _count++; // 增加元素数量
  30.     }
  31.     // FastClear 方法用于快速清空缓冲区
  32.     public void FastClear()
  33.     {
  34.         _start = 0;
  35.         _end = 0;
  36.         _count = 0;
  37.     }
  38.     // Count 属性返回缓冲区中的元素数量
  39.     public int Count => _count;
  40.     // First 属性返回缓冲区中的第一个元素
  41.     public T First => _elements[_start];
  42.     // Last 属性返回缓冲区中的最后一个元素
  43.     public T Last => _elements[(_start+_count-1)%_capacity];
  44.     // IsFull 属性指示缓冲区是否已满
  45.     public bool IsFull => _count == _capacity;
  46.     // RemoveFromStart 方法从缓冲区的开始移除指定数量的元素
  47.     public void RemoveFromStart(int count)
  48.     {
  49.         if(count > _capacity || count > _count)
  50.             throw new ArgumentException(); // 如果请求移除的元素数量不合法,则抛出异常
  51.         _start = (_start + count) % _capacity; // 更新_start索引
  52.         _count -= count; // 减少元素数量
  53.     }
  54.     // GetEnumerator 方法提供了遍历缓冲区的方法
  55.     public IEnumerator<T> GetEnumerator()
  56.     {
  57.         int counter = _start;
  58.         while (counter != _end)
  59.         {
  60.             yield return _elements[counter];
  61.             counter = (counter + 1) % _capacity;
  62.         }           
  63.     }
  64.     // IEnumerable 接口的实现,用于集合的迭代
  65.     IEnumerator IEnumerable.GetEnumerator()
  66.     {
  67.         return GetEnumerator();
  68.     }
  69. }
复制代码
来源:https://www.cnblogs.com/Mr147/archive/2023/12/01/17869704.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具