在Rust中打印单向链表的最佳方法

3

在努力学习Rust的过程中,我正在尝试找到在Rust中打印单向链表结构的最佳方法。以下是我编写的代码:

struct SList {
    n: int,
    next: Option<Box<SList>>
}

fn print_slist(mut l: &SList) {
    print!("{}", l.n);
    loop {
        match l.next {
            Some(ref next) => { print!(" -> {}", next.n); l = &(**next); },
            None => { break; }
        }
    }
    println!("");
}

fn main() {
    let sl1 = SList { n: 11, next: Some(box SList { n: 22, next: Some(box SList { n: 33, next: None })})};
    print_slist(&sl1);
}

我相信有更好的方法可以完成这个操作,我希望能够了解它们。除此之外,我还关心&(**next)部分。它是否会创建一个不必要的SList副本?
1个回答

4
你手头的代码已经很好了,其中next&Box<SList>类型,所以&**next就是&SList类型。
不过你可以通过在模式匹配中解引用box并直接获取&SList来使其更加简洁明了。
Some(box ref next) => {
    print!(" -> {}", next.n);
    l = next;
},

我建议将这种东西写成迭代器的形式。同时,实现std::fmt::Show而不是编写单独的函数。
以下是迭代和实现Show的示例实现:
use std::fmt;

struct SList {
    n: int,
    next: Option<Box<SList>>
}

struct SListIter<'a> {
    current: Option<&'a SList>,
}

impl SList {
    fn iter<'a>(&'a self) -> SListIter<'a> {
        SListIter {
            current: Some(self),
        }
    }
}

impl<'a> Iterator<int> for SListIter<'a> {
    fn next(&mut self) -> Option<int> {
        self.current.map(|current| {
            let value = current.n;
            self.current = match current.next {
                Some(box ref next) => Some(next),
                None => None
            };
            value
        })
    }
}

impl fmt::Show for SList {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut first = true;
        for value in self.iter() {
            if !first {
                try!(write!(f, " -> "));
            }
            try!(write!(f, "{}", value));
            first = false;
        }
        Ok(())
    }
}

fn main() {
    let sl1 = SList { n: 11, next: Some(box SList { n: 22, next: Some(box SList { n: 33, next: None })})};
    println!("{}", sl1);
}

非常好的回答!感谢您的快速回复。 - russoue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接