5个版本
0.2.2 | 2024年8月8日 |
---|---|
0.2.1 | 2024年8月5日 |
0.2.0 | 2024年8月5日 |
0.1.1 | 2024年7月31日 |
0.1.0 | 2024年7月30日 |
#329 in 数据结构
每月582次下载
40KB
820 行
RelRc
可能依赖于其他指针的引用计数指针。此crate复制了`std::rc::Rc`和`std::rc::Weak`的行为,但允许引用链接到其他引用。一个RelRc
对象(相当于`Rc`)将在有引用指向它或它的任何后代时保持存活。
我难道不能在我的`Rc`中只保留一个`Rc`的列表吗?
是的——这正是这个crate在底层所做的事情。然而,这个crate会为您跟踪额外的数据,从而提供额外的功能。
- 依赖关系可以向后遍历:[
RelRc::all_children(v)
]将返回所有依赖于`v`(父节点)的对象(子节点)。 - 数据可以存储在依赖边本身上。
- 使用
GraphView
和petgraph
(请确保激活`petgraph`功能)可以遍历生成的有向无环依赖图。
这个crate也可以被视为一个有向无环图(DAG)实现,其中当节点及其后代超出作用域时,节点会自动被移除。这是一个在新的对象可以被视为先前创建的对象的后代时自然出现的结构。例如,包括git历史中的提交、Merkle树...
节点不可变性
按照设计,就像 [Rc
] 一样,一旦创建,RelRc
及其父节点都是不可变的。可以添加新的 RelRc
作为节点的后代,但节点一旦创建就不能修改,直到所有对其的引用都被删除才会存在。
这确保了不会创建循环,消除了循环检查的需要,并保证了没有内存泄漏。如果需要可变的节点或边值,请考虑使用 RefCell
。
示例
use relrc::RelRc;
// Create a Rc pointer (equivalent to `Rc::new`)
let root = RelRc::new("root");
// Now child pointers can be created. Edge value: ()
let child = RelRc::with_parents("child", [(root.clone(), ())]);
// Create a grandchild pointer
let grandchild = RelRc::with_parents("grandchild", [(child.clone(), ())]);
// Obtain a second reference to the child pointer
let child_clone = child.clone();
assert_eq!(root.n_outgoing(), 1, "root has 1 outgoing edge");
assert_eq!(child.n_outgoing(), 1, "child has 1 outgoing edge");
// Drop the original child node
drop(child);
// The second child pointer still exists: outgoing edges remain the same
assert_eq!(root.n_outgoing(), 1, "root still has 1 outgoing edge");
assert_eq!(child_clone.n_outgoing(), 1, "child_clone still has 1 outgoing edge");
// Drop the second child pointer
drop(child_clone);
// Still no change at the root: grandchild node is still a descendant
assert_eq!(root.n_outgoing(), 1, "root still has 1 outgoing edge");
// Finally, dropping the grandchild leaves only the root node
drop(grandchild);
assert_eq!(root.n_outgoing(), 0, "root now has 0 outgoing edges");
依赖
~0.3–1.3MB
~25K SLoC