我曾试图重新实现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。
1条答案
按热度按时间xnifntxz1#
查看您的代码,head节点是您在中给予的节点
它的召唤
也就是说,它初始化时没有头节点,所以当你用一个节点构造你的列表时,你就添加了一个头
还可以通过显式地将新创建的列表作为self传递来调用append。
你可以称之为
您假设在测试中头部之外还有另一个节点: