Skip to content

Commit

Permalink
circular
Browse files Browse the repository at this point in the history
  • Loading branch information
tickbh committed Jun 13, 2024
1 parent 0f1fdf5 commit 595aab7
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 21 deletions.
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
## algorithm
将提供一些常用的数据结构以供使用。
将提供一些常用的数据结构以供使用。目前提供的数据结构
* **LruCache** 最近未使用缓存
* **LruKCache** 最近未使用缓存, K次分类列表
* **LfuCache** 按缓存访问次数做排序,优先淘汰访问最少次数的
* **Slab** 仿linux中的Slab结构,对大对象做到初始化缓存使用
* **BitMap** 位图, 按位做标记的图
* **RoaringBitMap** 位图, 因为位图占用的内存太大, 对于稀疏位图会更小内存
* **TimerWheel** 计时器轮, 模仿时钟的高效定时器组件
* **CircularBuffer** 环形Buffer组件, 适用于内存限定较严格的, 设置不超过缓存值的环形结构
* **RBTree** 红黑村, 高效的排序树, 可用于做定时器组件

# lru 全称是Least Recently Used,即最近最久未使用的意思。
每次元素访问将其更新到列表的最前,时间复杂度为O(1)。当达到容量限制时将淘汰双向列表中的链尾数据
Expand Down
4 changes: 2 additions & 2 deletions examples/circular.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ fn main() {
circular.push_back(2);
circular.push_back(3);
assert_eq!(circular.len(), 2);
assert_eq!(circular[&0], 2);
assert_eq!(circular[&1], 3);
assert_eq!(circular[0], 2);
assert_eq!(circular[1], 3);
}
134 changes: 116 additions & 18 deletions src/arr/circular_buffer.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::ops::{Index, IndexMut};
use std::{marker::PhantomData, ops::{Index, IndexMut}};

/// 循环的圆结构
/// 如果数据满了之后将自动在结尾后续添加,并保持最大个数
Expand All @@ -13,8 +13,8 @@ use std::ops::{Index, IndexMut};
/// circular.push_back(2);
/// circular.push_back(3);
/// assert_eq!(circular.len(), 2);
/// assert_eq!(circular[&0], 2);
/// assert_eq!(circular[&1], 3);
/// assert_eq!(circular[0], 2);
/// assert_eq!(circular[1], 3);
/// }
/// ```
pub struct CircularBuffer<T> {
Expand Down Expand Up @@ -139,7 +139,7 @@ impl<T> CircularBuffer<T> {
/// assert_eq!(circular.is_empty(), true);
/// circular.push_back(1);
/// circular.push_back(2);
/// assert_eq!(circular[&0], 1);
/// assert_eq!(circular[0], 1);
/// }
/// ```
pub fn push_back(&mut self, val: T) {
Expand Down Expand Up @@ -170,7 +170,7 @@ impl<T> CircularBuffer<T> {
/// assert_eq!(circular.is_empty(), true);
/// circular.push_front(1);
/// circular.push_front(2);
/// assert_eq!(circular[&0], 2);
/// assert_eq!(circular[0], 2);
/// }
/// ```
pub fn push_front(&mut self, val: T) {
Expand Down Expand Up @@ -202,9 +202,9 @@ impl<T> CircularBuffer<T> {
/// assert_eq!(circular.is_empty(), true);
/// circular.push_front(1);
/// circular.push_front(2);
/// assert_eq!(circular[&0], 2);
/// assert_eq!(circular[0], 2);
/// circular.pop_front();
/// assert_eq!(circular[&0], 1);
/// assert_eq!(circular[0], 1);
/// }
/// ```
pub fn pop_front(&mut self) {
Expand All @@ -224,9 +224,9 @@ impl<T> CircularBuffer<T> {
/// assert_eq!(circular.is_empty(), true);
/// circular.push_back(1);
/// circular.push_back(2);
/// assert_eq!(circular[&0], 1);
/// assert_eq!(circular[0], 1);
/// circular.pop_back();
/// assert_eq!(circular[&0], 1);
/// assert_eq!(circular[0], 1);
/// }
/// ```
pub fn pop_back(&mut self) {
Expand Down Expand Up @@ -261,28 +261,56 @@ impl<T> CircularBuffer<T> {
cap: self.cap,
}
}

/// 迭代更改器
///
/// # Examples
///
/// ```
/// use algorithm::CircularBuffer;
/// fn main() {
/// let mut circular = CircularBuffer::new(2);
/// assert_eq!(circular.is_empty(), true);
/// circular.push_back(1);
/// circular.push_back(2);
/// let val: Vec<i32> = circular.iter_mut().map(|v| { *v *= 2; *v }).collect();
/// assert_eq!(val, vec![2, 4]);
/// let val: Vec<i32> = circular.iter_mut().rev().map(|v| { *v *= 2; *v }).collect();
/// assert_eq!(val, vec![8, 4]);
/// }
/// ```
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
arr: self.arr.as_mut_ptr(),
len: self.len,
head: self.head,
tail: self.tail,
cap: self.cap,
_marker: PhantomData,
}
}
}


impl<T> Index<&usize> for CircularBuffer<T> {
impl<T> Index<usize> for CircularBuffer<T> {
type Output = T;

#[inline]
fn index(&self, index: &usize) -> &T {
if *index < self.len {
let ridx = (*index + self.head) % self.cap;
fn index(&self, index: usize) -> &T {
if index < self.len {
let ridx = (index + self.head) % self.cap;
&self.arr[ridx]
} else {
panic!("index error");
}
}
}

impl<T> IndexMut<&usize> for CircularBuffer<T> {
impl<T> IndexMut<usize> for CircularBuffer<T> {
#[inline]
fn index_mut(&mut self, index: &usize) -> &mut T {
if *index < self.len {
let ridx = (*index + self.head) % self.cap;
fn index_mut(&mut self, index: usize) -> &mut T {
if index < self.len {
let ridx = (index + self.head) % self.cap;
&mut self.arr[ridx]
} else {
panic!("index error");
Expand Down Expand Up @@ -341,15 +369,85 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
}
}

pub struct IterMut<'a, T: 'a> {
len: usize,
arr: *mut T,
head: usize,
tail: usize,
cap: usize,
_marker: PhantomData<&'a mut T>,
}

impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;

fn next(&mut self) -> Option<Self::Item> {
if self.len == 0 {
return None;
}
let now = self.head;
self.head = (self.head + 1) % self.cap;
self.len -= 1;
unsafe {
let ptr = self.arr.add(now);
return Some(&mut *ptr)
}
}

fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}


impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.len == 0 {
return None;
}
let now = self.tail;
self.tail = (self.tail + self.cap - 1) % self.cap;
self.len -= 1;
unsafe {
let ptr = self.arr.add(now);
return Some(&mut *ptr)
}
}
}



impl<T> PartialEq for CircularBuffer<T>
where
T: Eq,
{
fn eq(&self, other: &CircularBuffer<T>) -> bool {
if self.len() != other.len() {
return false;
}

self.iter().enumerate().all(|(idx, value)| &other[idx] == value)
}
}

impl<T> Eq for CircularBuffer<T>
where
T: Eq,
{}

#[cfg(test)]
mod tests {
use super::CircularBuffer;

#[test]
fn test_iter() {

let mut circular = CircularBuffer::new(2);
assert_eq!(circular.is_empty(), true);
circular.push_back(1);
circular.push_back(2);
let val: Vec<i32> = circular.iter().map(|s| *s).collect();
assert_eq!(val, vec![1, 2]);
let val: Vec<i32> = circular.iter().rev().map(|s| *s).collect();
assert_eq!(val, vec![2, 1]);
}
}

0 comments on commit 595aab7

Please sign in to comment.