Rust 中的单链表
Posted
技术标签:
【中文标题】Rust 中的单链表【英文标题】:Singly-Linked List in Rust 【发布时间】:2022-01-09 14:44:12 【问题描述】:我最近一直在尝试自学一些 Rust,并想通过实现一个简单的链表来练习一下。我从 Rust 库的链表中获得了一些灵感,并尝试复制我已经理解的部分。我还决定暂时将其设为单链接。
struct Node<T>
element: T,
next: Option<Box<Node<T>>>,
impl<T> Node<T>
fn new(element: T) -> Self
Node
element: element,
next: None,
fn append(&mut self, element: Box<Node<T>>)
self.next = Some(element);
pub struct LinkedList<T>
head: Option<Box<Node<T>>>,
tail: Option<Box<Node<T>>>,
len: u32,
impl<T> LinkedList<T>
pub fn new() -> Self
head: None,
tail: None,
len: 0,
pub fn push(&mut self, element: T)
let node: Box<Node<T>> = Box::new(Node::new(element));
match self.tail
None => self.head = Some(node),
Some(mut ref tail) => tail.append(node),
self.tail = Some(node);
self.len += 1;
pub fn pop(&mut self) -> Option<T>
//not implemented
pub fn get(&self, index: u32) -> Option<T>
//not implemented
这是我到目前为止所得到的;据我了解,这段代码的问题是Box
不能有多个引用以保护内存安全。
所以当我将列表头设置为节点时
None => self.head = Some(node),
我不能继续设置
self.tail = Some(node);
稍后,我的理解到目前为止是否正确?这样做的正确方法是什么?我必须像在库中那样使用Shared
,还是有办法可以使用Box
或其他类型?
【问题讨论】:
obligatory reference (Learning Rust With Entirely Too Many Linked Lists) 请注意,传统的单链接(Cons List)不会记住tail
。这是一种允许在 O(1) 中追加的方法,但不是必需的。
@Oliver 如果它回答了你的问题,你能接受 Ijedrzs 的回答吗?否则请说明缺少的内容。
【参考方案1】:
你可以使用比这更简单的东西,只使用你的节点
use std::fmt;
struct Payload
id: i32,
value: i32,
impl fmt::Display for Payload
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
write!(f, "(, )", self.id, self.value)
struct Node<T>
element: T,
next: Option<Box<Node<T>>>,
impl<T> Node<T> where T: std::fmt::Display
fn new(element: T) -> Self
Node
element: element,
next: None,
fn append(&mut self, element: T)
match &mut self.next
None => let n = Node
element: element,
next: None,
;
self.next = Some(Box::new(n));
,
Some(ref mut x) => x.append(element),
fn list(& self)
println!("", self.element);
match &self.next
None => ,
Some(x) => x.list(),
fn main()
let mut h = Node::new(Payload id:1, value:1);
h.append(Payload id:2, value:2);
h.append(Payload id:3, value:3);
h.append(Payload id:4, value:4);
h.append(Payload id:5, value:5);
h.list();
h.append(Payload id:6, value:6);
h.list();
【讨论】:
所以它是递归的append
,它是非性能的
@prehistoricpenguin 如果我们只迭代元素并执行它而不是递归会更好吗?【参考方案2】:
您的问题是您在移动某个值 (node
) 后尝试使用它;由于Box<Node<T>>
没有实现Copy
,当你在match
表达式中使用它时:
match self.tail
None => self.head = Some(node),
Some(ref mut tail) => tail.append(node),
node
被移动到 self.head
或 self.tail
,以后不能再使用。除了阅读必读的 Learning Rust With Entirely Too Many Linked Lists 以了解在 Rust 中实现链表的不同方式之外,我建议您首先在 Rust 的基本概念领域做更多的研究,尤其是:
【讨论】:
以上是关于Rust 中的单链表的主要内容,如果未能解决你的问题,请参考以下文章
数据结构学习笔记(单链表单循环链表带头双向循环链表)的增删查改排序等)
数据结构学习笔记(单链表单循环链表带头双向循环链表)的增删查改排序等)