Rust:如何实现链表?

时间:2014-01-16 02:42:25

标签: rust

我以为我会通过改进一些非常简单的结构而潜入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);
    }
}

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

2 个答案:

答案 0 :(得分:6)

看起来您正在尝试使用自己的列表来查找最终元素,但实际上并没有循环。假设您已经解决了这个问题,可以使用ref mut代替ref修复可变性问题。

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

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

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

答案 1 :(得分:0)

迭代解决方案,使用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