在Rust中将节点附加到空的LinkedList,self.head.borrow_next()为None,而不是self.tail

cld4siwp  于 2022-12-29  发布在  其他
关注(0)|答案(1)|浏览(134)

我曾试图重新实现LinkedIn的 rust ,下面是我的代码:

#![allow(dead_code)]

use std::cell::{RefCell, Ref, RefMut};
use std::rc::Rc;

type WrappedNode<T> = Rc<RefCell<Node<T>>>;

#[derive(Debug, PartialOrd, PartialEq, Clone)]
pub struct Node<T> where
  T: Clone 
  {
    next: Option<WrappedNode<T>>,
    data: T,
}

#[derive(Debug, PartialOrd, PartialEq)]
pub struct LinkedList<T> where
  T: Clone 
  {
    head: Option<WrappedNode<T>>,
    tail: Option<WrappedNode<T>>,
}

impl<T> Iterator for LinkedList<T> where
  T: Clone 
  {
type Item = WrappedNode<T>;
  
  fn next(&mut self) -> Option<Self::Item> {
    unimplemented!()
  }
}

impl<T> Node<T> where
  T: Clone
  {
  pub fn new(data: T) -> Self {
    Self {
      next: None,
      data,
    }
  }

  pub fn borrow_data(self: &Self) -> &T {
    &self.data
  }

  pub fn borrow_next(self: &Self) -> Option<Ref<Node<T>>> {
    match &self.next {
      Some(next_exists) => {
        Some(next_exists.borrow())
      },
      None => {
        None
      }
    }
  }

  pub fn borrow_mut_next(self: &Self) -> Option<RefMut<Node<T>>> {
    match &self.next {
      Some(next_exists) => {
        Some(next_exists.borrow_mut())
      },
      None => {
        None
      }
    }
  }

  pub fn set_next(self: &mut Self, next: Node<T>) {
    let next_node = Rc::new(RefCell::new(next));
    self.next = Some(next_node);
  }
}

impl<T> LinkedList<T> where
  T: Clone
  {
  pub fn new_empty() -> Self {
    Self {
      head: None,
      tail: None,
    }
  }

  pub fn new_with_node(first_node: Node<T>) -> Self {
    let mut new_ll = Self::new_empty();
    Self::append(&mut new_ll, first_node);
    new_ll
  }

  pub fn append(&mut self, node: Node<T>) {
    assert!(node.next.is_none()); // make sure its not joining two linkedlists
    
    match self.tail.take() {
      Some(old_tail) => {
        old_tail
          .borrow_mut()
          .set_next(node.clone());
        },

      None => {
        let mut node_clone = node.clone();
        node_clone.next = self.tail.clone();
        self.head = Some(Rc::new(RefCell::new(node_clone)));
      }
    }
    self.tail = Some(Rc::new(RefCell::new(node)));
  }
  
}

// CRUD -> create new, add to head tail, read head tail, update anywhere, delete anywhere, delete head tail

#[cfg(test)]
mod tests {
  use super:: {Node, LinkedList};
  use std::rc::Rc;
  use std::cell::RefCell;
  
  #[test]
  fn test_node_ref_data() {
    let node = Node::new(5);
    assert_eq!(node.borrow_data(), &5);
  }

  #[test]
  fn test_node_ref_next() {
    let node = Node::new(5);
  assert!(node.borrow_next().is_none());
  }

  #[test]
  fn test_node_set_next() {
    let mut node = Node::new(33);
    let next_node = Node::new(34);
    Node::set_next(&mut node,
                   next_node);
    assert_eq!(node
               .borrow_next()
               .unwrap()
               .borrow_data(), &34);
  }

  #[test]
  fn test_ll_new_empty() {
    #[derive(Debug, PartialEq, PartialOrd, Clone)]
    struct NTH;
    let new_ll = LinkedList::<NTH>::new_empty();
    assert_eq!(new_ll, LinkedList{head: None, tail: None})
  }

  #[test]
  fn test_ll_new_with_node() {
    let new_node = Node::new(45);
    let new_node_two = new_node.clone();
    let new_node_three = new_node.clone();
    let new_ll = LinkedList::new_with_node(new_node);
    let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));
    let new_node_three = Some(Rc::new(RefCell::new(new_node_three)));
    
    assert_eq!(new_ll, LinkedList{head: new_node_two, tail: new_node_three})
  }

  #[test]
  fn test_ll_new_with_node_head_borrow_next_is_tail() {
    let new_node = Node::new(45);
    let new_node_two = new_node.clone();
    let new_ll = LinkedList::new_with_node(new_node);
    let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));
    assert_eq!(new_ll
            .head
            .unwrap()
            .borrow()
            .borrow_next()
            .unwrap()
            .borrow_data(), new_node_two.unwrap().borrow().borrow_data());
  }

  #[test]
  fn test_ll_append_tail() {
    let new_node = Node::new(45);
    let new_node_two = new_node.clone();
    let mut new_ll = LinkedList::new_with_node(new_node);
    let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));

    let append_node = Node::new(77);
    LinkedList::append(&mut new_ll, append_node);
    assert_eq!(new_ll
              .tail
              .unwrap()
              .borrow()
              .borrow_data(), &77)
  }

  #[test]
  fn test_ll_append_first_borrow_next() {
    let new_node = Node::new(45);
    let new_node_two = new_node.clone();
    let mut new_ll = LinkedList::new_with_node(new_node);
    let new_node_two = Some(Rc::new(RefCell::new(new_node_two)));

    let append_node = Node::new(77);
    LinkedList::append(&mut new_ll, append_node);
    assert_eq!(new_ll
              .head
              .unwrap()
              .borrow()
              .borrow_next()
              .unwrap()
              .borrow_data(), &77)
  }

// end of tests
}

两个测试失败,如下所示:

running 8 tests
test same_type_linked_list::tests::test_ll_new_empty ... ok
test same_type_linked_list::tests::test_ll_append_tail ... ok
test same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail ... FAILED
test same_type_linked_list::tests::test_ll_append_first_borrow_next ... FAILED
test same_type_linked_list::tests::test_ll_new_with_node ... ok
test same_type_linked_list::tests::test_node_ref_data ... ok
test same_type_linked_list::tests::test_node_set_next ... ok
test same_type_linked_list::tests::test_node_ref_next ... ok

failures:

---- same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail stdout ----
thread 'same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail' panicked at 'called `Option::unwrap()` on a `None` value', src/same_type_linked_list.rs:176:14

---- same_type_linked_list::tests::test_ll_append_first_borrow_next stdout ----
thread 'same_type_linked_list::tests::test_ll_append_first_borrow_next' panicked at 'called `Option::unwrap()` on a `None` value', src/same_type_linked_list.rs:210:16
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

failures:
    same_type_linked_list::tests::test_ll_append_first_borrow_next
    same_type_linked_list::tests::test_ll_new_with_node_head_borrow_next_is_tail

我怀疑在向空的LinkedList追加新的Node<T>(具体为Node<u64>)时,self.head.next没有指向self.tail,尽管我明确地设置了它。当我对borrow_next()返回的None值调用unwrap()时,错误发生。Node<T>的关联方法返回字段.next的引用。这意味着理想情况下应该返回对new_ll.tail的引用的new_ll.head.borrow_next()改为返回None,这意味着当第一节点被附加/插入到完全空的LinkedList中时,它不指向new_11.tail。

xnifntxz

xnifntxz1#

查看您的代码,head节点是您在中给予的节点

LinkedList::new_with_node()

它的召唤

pub fn new_empty() -> Self {
    Self {
      head: None,
      tail: None,
    }

也就是说,它初始化时没有头节点,所以当你用一个节点构造你的列表时,你就添加了一个头

pub fn new_with_node(first_node: Node<T>) -> Self {
    let mut new_ll = Self::new_empty();
    Self::append(&mut new_ll, first_node);
    new_ll
  }

  pub fn append(&mut self, node: Node<T>) {
    assert!(node.next.is_none()); // make sure its not joining two linkedlists
    
    match self.tail.take() {
      Some(old_tail) => {
        old_tail
          .borrow_mut()
          .set_next(node.clone());
        },

      None => {
        let mut node_clone = node.clone();
        node_clone.next = self.tail.clone();
        self.head = Some(Rc::new(RefCell::new(node_clone)));
      }
    }

还可以通过显式地将新创建的列表作为self传递来调用append。

Self::append(&mut new_ll, first_node);

你可以称之为

new_ll.append(first_node)

您假设在测试中头部之外还有另一个节点:

assert_eq!(new_ll
              .head
              .unwrap()
              .borrow()
              .borrow_next()
              .unwrap()
              .borrow_data(), &77)

相关问题