linked list remove action tested

This commit is contained in:
Víctor Martínez 2020-12-06 19:43:44 +01:00
parent 8c8b9e12ab
commit 6adebe2d69
3 changed files with 120 additions and 63 deletions

View file

@ -1,4 +1,4 @@
pub use crate::models::linked_list::{Node, SharedNode};
use crate::models::linked_list::{Node, SharedNode};
use std::{cell::RefCell, rc::Rc};
pub struct DoublyLinkedList<T> {
@ -10,11 +10,11 @@ impl<T> DoublyLinkedList<T> {
pub fn new() -> Self {
DoublyLinkedList {
length: 0,
root: Rc::new(RefCell::new(Some(Node {
root: Rc::new(RefCell::new(Node {
elem: None,
next: Node::new_shared(None),
prev: Node::new_shared(None),
}))),
next: None,
prev: None,
})),
}
}
@ -26,49 +26,70 @@ impl<T> DoublyLinkedList<T> {
let node = Node::new_shared(Some(value));
if self.length == 0 {
Node::set_next(&self.root, &node);
Node::set_prev(&node, &self.root);
Node::set_next(&self.root, Some(&node));
Node::set_prev(&node, Some(&self.root));
} else {
let last = Node::get_prev(&self.root);
Node::set_next(&last, &node);
Node::set_prev(&node, &last);
let last = Node::get_prev(&self.root).unwrap();
Node::set_next(&last, Some(&node));
Node::set_prev(&node, Some(&last));
}
Node::set_prev(&self.root, &node);
Node::set_next(&node, &self.root);
Node::set_prev(&self.root, Some(&node));
Node::set_next(&node, Some(&self.root));
self.length += 1;
}
pub fn push_first(&mut self, value: T) {
let node = Node::new_shared(Some(value));
if self.length == 0 {
Node::set_prev(&self.root, &node);
Node::set_next(&node, &self.root);
Node::set_prev(&self.root, Some(&node));
Node::set_next(&node, Some(&self.root));
} else {
let first = Node::get_next(&self.root);
Node::set_prev(&first, &node);
Node::set_next(&node, &first);
let first = Node::get_next(&self.root).unwrap();
Node::set_prev(&first, Some(&node));
Node::set_next(&node, Some(&first));
}
Node::set_next(&self.root, &node);
Node::set_prev(&node, &self.root);
Node::set_next(&self.root, Some(&node));
Node::set_prev(&node, Some(&self.root));
self.length += 1;
}
pub fn get(&self, index: u64) -> SharedNode<T> {
pub fn get(&self, index: u64) -> Option<Rc<RefCell<T>>> {
self._get_node(index).and_then(|rc| Node::get_elem(&rc))
}
pub fn remove(&mut self, index: u64) -> Result<(), String> {
let node = self._get_node(index).ok_or(String::from("Invalid index"))?;
let prev = Node::get_prev(&node).unwrap();
let next = Node::get_next(&node).unwrap();
Node::set_next(&prev, Some(&next));
Node::set_prev(&next, Some(&prev));
if self.length == 1 {
Node::set_next(&self.root, None);
Node::set_prev(&self.root, None);
}
self.length -= 1;
Ok(())
}
fn _get_node(&self, index: u64) -> Option<SharedNode<T>> {
if self.length == 0 || index >= self.length {
return Node::new_shared(None);
return None;
}
let mut current = Rc::clone(&self.root);
if index < self.length / 2 {
for _ in 0..index + 1 {
current = Node::get_next(&current);
current = Node::get_next(&current).unwrap();
}
} else {
for _ in 0..self.length - index {
current = Node::get_prev(&current);
current = Node::get_prev(&current).unwrap();
}
}
current
Some(Rc::clone(&current))
}
}

View file

@ -1,46 +1,50 @@
use std::{cell::RefCell, rc::Rc};
pub type SharedNode<T> = Rc<RefCell<Option<Node<T>>>>;
pub type SharedNode<T> = Rc<RefCell<Node<T>>>;
#[allow(dead_code)]
pub struct Node<T> {
pub elem: Option<T>,
pub next: SharedNode<T>,
pub prev: SharedNode<T>,
pub elem: Option<Rc<RefCell<T>>>,
pub next: Option<SharedNode<T>>,
pub prev: Option<SharedNode<T>>,
}
impl<T> Node<T> {
pub fn new_shared(value: Option<T>) -> SharedNode<T> {
Rc::new(RefCell::new(Some(Node {
elem: value,
next: Rc::new(RefCell::new(None)),
prev: Rc::new(RefCell::new(None)),
})))
}
pub fn is_none(node: &SharedNode<T>) -> bool {
node.borrow_mut().is_none()
Rc::new(RefCell::new(Node {
elem: value.map(|elem| Rc::new(RefCell::new(elem))),
next: None,
prev: None,
}))
}
pub fn get_prev(node: &SharedNode<T>) -> SharedNode<T> {
Rc::clone(&(*node.borrow_mut()).as_mut().unwrap().prev)
pub fn get_elem(node: &SharedNode<T>) -> Option<Rc<RefCell<T>>> {
let node = node.borrow();
match &node.elem {
Some(rc) => Some(Rc::clone(&rc)),
None => None,
}
}
pub fn get_next(node: &SharedNode<T>) -> SharedNode<T> {
Rc::clone(&(*node.borrow_mut()).as_mut().unwrap().next)
pub fn get_prev(node: &SharedNode<T>) -> Option<SharedNode<T>> {
let ref mut node = *node.borrow_mut();
node.prev.as_ref().and_then(|prev| Some(Rc::clone(prev)))
}
pub fn set_prev(node: &SharedNode<T>, to: &SharedNode<T>) {
pub fn get_next(node: &SharedNode<T>) -> Option<SharedNode<T>> {
let ref mut node = *node.borrow_mut();
node.next.as_ref().and_then(|next| Some(Rc::clone(next)))
}
pub fn set_prev(node: &SharedNode<T>, to: Option<&SharedNode<T>>) {
let node = Rc::clone(node);
let ref mut node = *node.borrow_mut();
let node = node.as_mut().unwrap();
node.prev = Rc::clone(to);
node.prev = to.map(|rc| Rc::clone(rc));
}
pub fn set_next(node: &SharedNode<T>, to: &SharedNode<T>) {
pub fn set_next(node: &SharedNode<T>, to: Option<&SharedNode<T>>) {
let node = Rc::clone(node);
let ref mut node = *node.borrow_mut();
let node = node.as_mut().unwrap();
node.next = Rc::clone(to);
node.next = to.map(|rc| Rc::clone(rc));
}
}

View file

@ -1,11 +1,4 @@
use data_structs::linked_list::{DoublyLinkedList, SharedNode, Node};
fn get_elem(node: SharedNode<i32>) -> i32 {
let ref result = node.borrow();
let opt = result.as_ref().unwrap();
opt.elem.unwrap()
}
use data_structs::linked_list::DoublyLinkedList;
#[test]
fn test_push() {
@ -13,11 +6,11 @@ fn test_push() {
link_list.push(3);
link_list.push(5);
let res1 = get_elem(link_list.get(0));
let res2 = get_elem(link_list.get(1));
let res1 = link_list.get(0).unwrap();
let res2 = link_list.get(1).unwrap();
assert_eq!(res1, 3);
assert_eq!(res2, 5);
assert_eq!(*res1.borrow(), 3);
assert_eq!(*res2.borrow(), 5);
}
#[test]
@ -26,10 +19,49 @@ fn test_push_first() {
link_list.push_first(3);
link_list.push_first(5);
let res1 = get_elem(link_list.get(0));
let res2 = get_elem(link_list.get(1));
let res1 = link_list.get(0).unwrap();
let res2 = link_list.get(1).unwrap();
assert_eq!(res1, 5);
assert_eq!(res2, 3);
assert_eq!(*res1.borrow(), 5);
assert_eq!(*res2.borrow(), 3);
}
#[test]
fn test_combine_push() {
let mut link_list: DoublyLinkedList<i32> = DoublyLinkedList::new();
link_list.push(3);
link_list.push_first(23);
link_list.push(10);
link_list.push_first(5);
let res1 = link_list.get(0).unwrap();
let res2 = link_list.get(1).unwrap();
let res3 = link_list.get(2).unwrap();
let res4 = link_list.get(3).unwrap();
let res5 = link_list.get(4);
assert_eq!(*res1.borrow(), 5);
assert_eq!(*res2.borrow(), 23);
assert_eq!(*res3.borrow(), 3);
assert_eq!(*res4.borrow(), 10);
assert!(res5.is_none());
}
#[test]
fn test_remove() {
let mut link_list: DoublyLinkedList<i32> = DoublyLinkedList::new();
link_list.push(3);
link_list.push(10);
link_list.push(40);
assert_eq!(link_list.length(), 3);
link_list.remove(2).unwrap();
assert_eq!(link_list.length(), 2);
let n = link_list.get(1).unwrap();
assert_eq!(*n.borrow(), 10);
assert!(link_list.get(2).is_none());
}