Hi guys, this is Kevin here. 今天想给大家锻炼一个rust的底层数据结构的设计能力的题目,同时为了帮自己加深对rust的理解。好的,现在直接进入正题。
题目
实现:
rust
struct LruCache<K, V>{...}
支持:
new(capacity: usize) -> Selfget(&mut self, key: &K) -> Option<&V>put(&mut self, key: K, value: V)- 超过容量时淘汰最近最少使用的元素 要求:
get后要更新最近使用顺序- 时间复杂度尽量做到接近
O(1)
考点
HashMap- 双向链表
Rc<RefCell<_>>/Box/ 裸指针取舍- 可变借用冲突怎么规避
- 数据结构设计能力
实现思路: LRU - 全称least-recent-used(最近最少使用)
Solution 1:
Hashmap + Vec
rust
因为hashmap查找复杂度0(1), 更新顺序的话: 0(n) Vec中需要移除并添加
所以这个不太满足
Solution 2:
HashMap + 双向链表 + 裸指针
rust
HashMap<K, *mut Node<V>> // 直接存指针
性能: 最优
风险: 内存安全性难以保证,容易段错误
不推荐用于生产环境
Solution 3:
HashMap + 双向链表 + Rc<RefCell<_>>
rust
HashMap<K, Rc<RefCell<Node<V>>>>
性能: O(1)
安全性: 完全的内存安全
可维护性: 高
关键结构:
rust
struct Node<V> {
value: V,
prev: Option<Rc<RefCell<Node<V>>>>,
next: Option<Rc<RefCell<Node<V>>>>,
}
struct LruCache<K, V> {
capacity: usize,
cache: HashMap<K, Rc<RefCell<Node<V>>>>,
head: Option<Rc<RefCell<Node<V>>>>, // 最近使用
tail: Option<Rc<RefCell<Node<V>>>>, // 最少使用
}
See complete implementation, please refers to:
同时,unit test已经都pass了

最后的summary
好啦,其实如果手动实现的话,确实需要做一个详细的分析,才能真正从中领悟他的hashmap的底层实现和所有权机制。今天的分享就到这里, thanks for reading.