有没有办法遍历可变树以获得随机节点? [英] Is there a way to iterate over a mutable tree to get a random node?
问题描述
我正在尝试更新树结构的节点.随机选择要更新的节点.要使用 Reservoir Sampling 算法对树中的节点进行采样,我必须遍历这些节点,因此我尝试为我的 Node
枚举创建一个 Iterator
.>
问题是,一方面,我必须在堆栈或队列中存储子节点的引用,但另一方面,我必须返回父节点的可变引用.Rust 不允许为一个值创建多个可变引用,也不允许将不可变引用转换为可变引用.
有没有办法遍历可变树?或者是否有另一种方法可以随机获取对树中节点的可变引用?
这是我的代码.
#![feature(box_syntax, box_patterns)]外部板条箱兰特;//简单的二叉树结构#[派生(调试)]枚举节点{叶(u8),分支(框<节点>,框<节点>),}实现节点{fn iter_mut(&mut self) ->迭代器{迭代器{堆栈: vec![self],}}fn pick_random_node_mut<'a>(&'a mut self) ->&'一个mut节点{//Revervoir采样让 rng = &mut rand::thread_rng();rand::seq::sample_iter(rng, self.iter_mut(), 1).ok().and_then(|mut v| v.pop()).unwrap()}}//`Node` 的迭代器struct IterMut<'a>{堆栈:Vec<&'a mut Node>,}impl <'a>IterMut<'a>的迭代器{type Item = &'a mut Node;fn next(&mut self) ->选项<&'a mut Node>{让节点 = self.stack.pop()?;//我被困在这里:不能一次多次借用 `*node` 作为可变的if let &mut Node::Branch(box ref mut a, box ref mut b) = node {self.stack.push(b);self.stack.push(a);}一些(节点)}}fn 主(){使用节点::*;let mut tree: Node = Branch(box Leaf(1), box Leaf(2));println!("{:?}", 树);{让节点:&mut Node = tree.pick_random_node_mut();*节点=叶(3);}println!("{:?}", 树);}
不,编写对树节点的可变引用的迭代器是不安全的.
假设我们有这个树结构:
+-++----+ +----+|+-+ |||||+--v-+ +--v--+|50 ||100 |+----+ +-----+
如果存在这样的迭代器,我们可以这样称呼它:
let mut all_nodes: Vec<&mut Node>= tree.iter_mut().collect();
假设父节点在索引 0 中结束,左节点在索引 1 中,右节点在索引 2 中.
let (head, tail) = all_nodes.split_at_mut(1);让 x = 匹配 &mut head[0] {Branch(ref mut l, _) =>升,叶(_) =>无法访问!(),};让 y = &mut tail[1];
现在 x
和 y
是彼此可变的别名.我们在完全安全的代码中违反了基本的 Rust 要求.这就是为什么这样的迭代器是不可能的.
您可以实现对树中值的可变引用的迭代器:
impl<'a>IterMut<'a>的迭代器{type Item = &'a mut u8;fn next(&mut self) ->选项<Self::Item>{环形 {让节点 = self.stack.pop()?;匹配节点{节点::分支(a, b) =>{self.stack.push(b);self.stack.push(a);}节点::叶(l) =>返回一些(l),}}}}
这是安全的,因为没有办法从一个可变引用到另一个值.然后,您可以在此基础上构建您的随机选择:
<代码>{让rando = 匹配rand::seq::sample_iter(&mut rand::thread_rng(), tree.iter_mut(), 1) {Ok(mut v) =>v.pop().unwrap(),错误(_)=>恐慌!(没有足够的元素"),};*随机+= 1;}
I am trying to update a node of a tree structure. A node which is to be updated is selected randomly. To sample a node in the tree using the Reservoir Sampling algorithm, I have to iterate over the nodes, so I have tried to make an Iterator
for my Node
enum.
The problem is that, on the one hand, I have to store references for child nodes in a stack or queue, however on the other hand, I have to return a mutable reference for a parent node. Rust does not allow to make multiple mutable references for one value, neither to convert an immutable reference into a mutable reference.
Is there a way to iterate over a mutable tree? Or is there another approach to randomly get a mutable reference to a node in a tree?
Here is my code.
#![feature(box_syntax, box_patterns)]
extern crate rand;
// Simple binary tree structure
#[derive(Debug)]
enum Node {
Leaf(u8),
Branch(Box<Node>, Box<Node>),
}
impl Node {
fn iter_mut(&mut self) -> IterMut {
IterMut {
stack: vec![self],
}
}
fn pick_random_node_mut<'a>(&'a mut self) -> &'a mut Node {
// Revervoir sampling
let rng = &mut rand::thread_rng();
rand::seq::sample_iter(rng, self.iter_mut(), 1)
.ok().and_then(|mut v| v.pop()).unwrap()
}
}
// An iterator for `Node`
struct IterMut<'a> {
stack: Vec<&'a mut Node>,
}
impl <'a> Iterator for IterMut<'a> {
type Item = &'a mut Node;
fn next(&mut self) -> Option<&'a mut Node> {
let node = self.stack.pop()?;
// I am stucking here: cannot borrow `*node` as mutable more than once at a time
if let &mut Node::Branch(box ref mut a, box ref mut b) = node {
self.stack.push(b);
self.stack.push(a);
}
Some(node)
}
}
fn main() {
use Node::*;
let mut tree: Node = Branch(box Leaf(1), box Leaf(2));
println!("{:?}", tree);
{
let node: &mut Node = tree.pick_random_node_mut();
*node = Leaf(3);
}
println!("{:?}", tree);
}
No, it is not safe to write an iterator of the mutable references to the nodes of a tree.
Assume we have this tree structure:
+-+
+----+ +----+
| +-+ |
| |
| |
+--v-+ +--v--+
| 50 | | 100 |
+----+ +-----+
If such an iterator existed, we could call it like this:
let mut all_nodes: Vec<&mut Node> = tree.iter_mut().collect();
Assume that the parent node ends up in index 0, the left node in index 1, and the right node in index 2.
let (head, tail) = all_nodes.split_at_mut(1);
let x = match &mut head[0] {
Branch(ref mut l, _) => l,
Leaf(_) => unreachable!(),
};
let y = &mut tail[1];
Now x
and y
are mutable aliases to each other. We have violated a fundamental Rust requirement in completely safe code. That's why such an iterator is not possible.
You could implement an iterator of mutable references to the values in the tree:
impl<'a> Iterator for IterMut<'a> {
type Item = &'a mut u8;
fn next(&mut self) -> Option<Self::Item> {
loop {
let node = self.stack.pop()?;
match node {
Node::Branch(a, b) => {
self.stack.push(b);
self.stack.push(a);
}
Node::Leaf(l) => return Some(l),
}
}
}
}
This is safe because there's no way to go from one mutable reference to a value to another one. You can then build your random selection on top of that:
{
let rando = match rand::seq::sample_iter(&mut rand::thread_rng(), tree.iter_mut(), 1) {
Ok(mut v) => v.pop().unwrap(),
Err(_) => panic!("Not enough elements"),
};
*rando += 1;
}
这篇关于有没有办法遍历可变树以获得随机节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!