【问题标题】:Rust: How to implement linked list?Rust:如何实现链表?
【发布时间】:2014-01-16 02:42:25
【问题描述】:

我想我会通过实现一些非常简单的结构和算法来深入研究 Rust,我从一个链表开始。事实证明,事情并没有那么简单。到目前为止,这是我的代码:

enum List<T> 
{
    Node(T, ~List<T>),
    Nil
}

impl<T> List<T>
{
    fn new(vector: &[T]) -> List<T> { Nil }

    fn add(&mut self, item: T)
    {
        let tail = self;
        loop
        {
            match *tail
            {
                Node(_, ~ref next) => tail = next,
                Nil => break
            }
        }
        *tail = Node(item, ~Nil);
    }
}

这不会编译,因为由于不兼容的可变性, next 无法在 match 语句中分配给 tail。我知道这可以使用垃圾回收指针轻松完成,但这违背了练习的教育目的:我想知道如何在没有 Gc 或 Rc 指针的情况下做到这一点。

【问题讨论】:

    标签: rust


    【解决方案1】:

    看起来您正在尝试遍历自己的列表以找到最终元素,但实际上并没有循环。假设你解决了这个问题,你的可变性问题可以通过使用 ref mut 而不是 ref 来解决。

    为了自己尝试,我使用了add() 的递归实现,这很有效:

    fn add(&mut self, item: T) {
        match *self {
            Node(_, ref mut next) => next.add(item),
            Nil => *self = Node(item, ~Nil)
        }
    }
    

    由于可变借用的问题,我不确定如何使用迭代方法来实现这一点。

    【讨论】:

    • 谢谢!是的,有一个循环,但我在循环和递归方法之间来回走动,我想有些时候我失去了它。将编辑。
    【解决方案2】:

    迭代解决方案,使用Box::borrow_mut()

    #[derive(Debug)]
    enum List<T> {
        Node(T, Box<List<T>>),
        Nil
    }
    
    impl<T> List<T> {
        fn new() -> List<T> { List::Nil }
    
        fn add(&mut self, item: T) {
            use std::borrow::BorrowMut;
            
            let mut tail = self;
            while let Self::Node(_, next) = tail {
                tail = next.borrow_mut();
            }
            *tail = List::Node(item, Box::new(List::Nil));
        }
    }
    

    Playground link

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 2018-06-25
      • 2016-05-29
      相关资源
      最近更新 更多