链表实现中的参考

时间:2019-07-06 03:47:08

标签: rust

我正在尝试做Simple Linked List运动问题,但是我坚持执行pop()方法。我得到的错误对我来说不是很清楚。我想我不太习惯Rust的思维方式。

此外,由于编译器的建议,我添加了一堆我不太了解的as_ref()

我很想知道为什么我的工作方式比解决方案更有用。

pub struct SimpleLinkedList<T> {
    head: Option<Box<Node<T>>>,
}

struct Node<T> {
    data: T,
    next: Option<Box<Node<T>>>,
}

impl<T> SimpleLinkedList<T> {
    pub fn new() -> Self {
        unimplemented!()
    }

    pub fn len(&self) -> usize {
        unimplemented!()
    }

    pub fn push(&mut self, _element: T) {
        unimplemented!()
    }

    pub fn pop(&mut self) -> Option<T> {
        // Recursive function to return the before last element of the list
        fn get_before_last<'a, T>(
            prev: &'a Box<Node<T>>,
            current: &'a Box<Node<T>>,
        ) -> &'a Box<Node<T>> {
            match &current.next {
                Some(next_node) => get_before_last(&current, &next_node),
                None => &prev,
            }
        }

        // Check if the head is None
        match &self.head {
            None => return None,
            _ => (),
        };

        let before_last = &mut match &self.head {
            // Beginning of the recursion
            Some(node) => get_before_last(&node, node.next.as_ref().unwrap()),
            None => self.head.as_ref().unwrap(),
        };

        let to_pop = before_last.next.as_ref();
        before_last.next = None;

        Some(to_pop.unwrap().data)
    }
}

我收到以下错误:

error[E0594]: cannot assign to `before_last.next` which is behind a `&` reference
  --> src/lib.rs:48:9
   |
48 |         before_last.next = None;
   |         ^^^^^^^^^^^^^^^^ cannot assign

error[E0507]: cannot move out of borrowed content
  --> src/lib.rs:50:14
   |
50 |         Some(to_pop.unwrap().data)
   |              ^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

1 个答案:

答案 0 :(得分:1)

在您的代码中,before_last是不可变的。实际上,它是&mut &'a Box<Node>。因此,您无法为节点分配任何内容,因为它是对不可变节点的可变引用。

我能给您的最好建议是重新考虑实现。您可以在前面进行操作,而不是将其弹出并拖到链的末端。 创建一个新的装箱节点,删除头部并将其放在新节点的下一个字段中。然后新节点成为头。

这样,您就拥有了LIFO列表,而不必遍历整个列表即可进行推送和弹出,因此它也更加有效。推到最前面还可以减少所需的代码量。

我的解决方法是available on Exercism