Rust 红黑树锈迹斑斑,越来越';应为结构节点,找到可变引用';

Rust 红黑树锈迹斑斑,越来越';应为结构节点,找到可变引用';,rust,red-black-tree-insertion,Rust,Red Black Tree Insertion,我试图实现红黑树生锈。经过两天与编译器的斗争,我准备放弃,我在这里寻求帮助 这个问题对我帮助很大: 我查看了Rust中RB树的现有示例代码,但是我看到的所有示例代码都使用了某种形式的不安全操作或null,我们不应该在这里使用这些操作 我有以下代码: #[derive(Debug, Clone, PartialEq)] pub enum Colour { Red, Black, } type T_Node<T> = Option<Box<Node<T

我试图实现红黑树生锈。经过两天与编译器的斗争,我准备放弃,我在这里寻求帮助

这个问题对我帮助很大:

我查看了Rust中RB树的现有示例代码,但是我看到的所有示例代码都使用了某种形式的不安全操作或
null
,我们不应该在这里使用这些操作

我有以下代码:

#[derive(Debug, Clone, PartialEq)]
pub enum Colour {
    Red,
    Black,
}

type T_Node<T> = Option<Box<Node<T>>>;

#[derive(Debug, Clone, PartialEq)]
pub struct Node<T: Copy + Clone + Ord> {
    value: T,
    colour: Colour,
    parent: T_Node<T>,
    left: T_Node<T>,
    right: T_Node<T>,
}

impl<T: Copy + Clone + Ord> Node<T>
{
    pub fn new(value: T) -> Node<T>
    {
        Node {
            value: value,
            colour: Colour::Red,  // add a new node as red, then fix violations
            parent: None,
            left: None,
            right: None,
            // height: 1,
        }
    }

    pub fn insert(&mut self, value: T)
    {
        if self.value == value
        {
            return;
        }

        let mut leaf = if value < self.value { &mut self.left } else { &mut self.right };

        match leaf
        {
            None =>
            {
                let mut new_node = Node::new(value);
                new_node.parent = Some(Box::new(self));
                new_node.colour = Colour::Red;

                (*leaf) = Some(Box::new(new_node));
            },
            Some(ref mut leaf) =>
            {
                leaf.insert(value);
            }
        };
    }
}
#[派生(调试、克隆、部分Q)]
酒吧枚举颜色{
红色
黑色
}
类型T_Node=选项;
#[派生(调试、克隆、PartialEq)]
发布结构节点{
值:T,
颜色:颜色,
父节点:T_节点,
左:T_节点,
右:T_节点,
}
impl节点
{
pub fn new(值:T)->节点
{
节点{
价值:价值,
color:color::Red,//将新节点添加为红色,然后修复冲突
家长:没有,
左:没有,
右:没有,
//身高:1,,
}
}
发布fn插入(&mut self,值:T)
{
如果self.value==value
{
返回;
}
设mut-leaf=if-value
{
让mut new_node=node::new(值);
new_node.parent=Some(Box::new(self));
新节点颜色=颜色::红色;
(*leaf)=一些(Box::new(new_节点));
},
一些(参考多叶)=>
{
叶。插入(值);
}
};
}
}
new_node.parent=Some(Box::new(self))告诉我错误。
我理解错误发生的原因(
self
被声明为可变引用),我不知道如何解决这个问题,但我需要
self
成为可变引用,这样我就可以修改我的树(除非你能提出更好的建议)

我试图将
T_节点
声明为具有可变引用,而不仅仅是
节点
,但这只会产生更多问题

我也愿意接受关于更好地选择变量类型的建议


非常感谢您的帮助。

设计中存在一些缺陷,如果不做一些修改,就无法进一步改进

首先,
Box
不支持共享所有权,但您需要共享所有权,因为同一节点由父节点(rbtree.right/rbtree.left)和子节点(rbtree.parent)引用。为此你需要

因此,您需要切换到
Rc
,而不是
Box

类型T_节点=选项;
但这并不能解决问题。现在,您的节点位于
Rc
内部,
Rc
不允许对其内容进行变异(您可以通过进行变异,但这要求它是唯一的,在您的情况下,它不是常数)。除非你能变异一个节点,否则你将无法对你的树做很多事情

所以你需要使用。为此,我们将添加一个附加层

类型T_节点=选项;
现在,这将允许我们改变里面的内容

但这并不能解决问题。由于您还需要保留从子对象到父对象的引用,因此最终将创建一个引用循环

幸运的是:

为了使子节点知道其父节点,我们需要向节点结构定义中添加一个父字段。问题在于决定父母应该是什么类型。我们知道它不能包含Rc,因为这将创建一个引用循环,其中leaf.parent指向branch,branch.children指向leaf,这将导致它们的强_计数值永远不会为0。从另一个角度考虑关系,父节点应该拥有它的子节点:如果父节点被删除,它的子节点也应该被删除。但是,子节点不应该拥有其父节点:如果我们删除子节点,父节点应该仍然存在。这是一个弱引用的例子

所以我们需要child持有对parent的弱引用。这可以通过以下方式实现:

type Child=Option;
输入Parent=Option;
现在我们已经固定了大部分设计

我们应该做的另一件事是,不直接公开
节点
,而是将其封装在结构
RBTree
中,该结构将保存树的
,并且可以在
RBTree
上调用
插入
搜索
删除
等操作。这将使事情变得简单,实现将变得更符合逻辑

pub结构RBTree{
根:孩子,
}
现在,让我们编写一个类似于您的
insert
实现:

impl-RBTree{
发布fn插入(&mut self,值:T){
fn插入(子节点:&mut子节点,mut新节点:节点){
让child=child.as_ref().unwrap();
让mut child_mut_borrow=child.borrow_mut();
如果child_mut_borrow.value==new_node.value{
返回;
}
let leaf=如果子节点\u mut\u borrow.value>new\u node.value{
&多个孩子,多个借用,左
}否则{
&多孩子多借钱,对吗
};
火柴叶{
一些())=>{
插入(叶,新节点);
}
无=>{
new_node.parent=Some(Rc::降级(&child));
*叶=一些(Rc::new(RefCell::new(new_节点));
}
};
}
让mut new_node=node::new(值);
如果self.root.is_none(){
new_node.parent=无;
self.root=Some(Rc::new(RefCell::new(new_节点));
}否则{
//我们确保从不向insert()发送“无”
插入(&mut self.root,新节点);
}
}
}
我在
RBTr中定义了
insert
函数