part 2 except iterator

This commit is contained in:
ridethepig 2023-02-25 10:41:19 +00:00
parent bd5895814e
commit 1e4049204e
2 changed files with 59 additions and 16 deletions

View File

@ -1,24 +1,24 @@
use std::fmt; use std::fmt;
use std::option::Option; use std::option::Option;
pub struct LinkedList { pub struct LinkedList<T> {
head: Option<Box<Node>>, head: Option<Box<Node<T>>>,
size: usize, size: usize,
} }
struct Node { struct Node<T> {
value: u32, value: T,
next: Option<Box<Node>>, next: Option<Box<Node<T>>>,
} }
impl Node { impl<T> Node<T> {
pub fn new(value: u32, next: Option<Box<Node>>) -> Node { pub fn new(value: T, next: Option<Box<Node<T>>>) -> Node<T> {
Node {value: value, next: next} Node {value: value, next: next}
} }
} }
impl LinkedList { impl<T> LinkedList<T> {
pub fn new() -> LinkedList { pub fn new() -> LinkedList<T> {
LinkedList {head: None, size: 0} LinkedList {head: None, size: 0}
} }
@ -30,24 +30,26 @@ impl LinkedList {
self.get_size() == 0 self.get_size() == 0
} }
pub fn push_front(&mut self, value: u32) { pub fn push_front(&mut self, value: T) {
let new_node: Box<Node> = Box::new(Node::new(value, self.head.take())); let new_node: Box<Node<T>> = Box::new(Node::new(value, self.head.take()));
self.head = Some(new_node); self.head = Some(new_node);
self.size += 1; self.size += 1;
} }
pub fn pop_front(&mut self) -> Option<u32> { pub fn pop_front(&mut self) -> Option<T> {
let node: Box<Node> = self.head.take()?; let node: Box<Node<T>> = self.head.take()?;
self.head = node.next; self.head = node.next;
self.size -= 1; self.size -= 1;
Some(node.value) Some(node.value)
} }
} }
impl fmt::Display for LinkedList { impl<T:fmt::Display> fmt::Display for LinkedList<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut current: &Option<Box<Node>> = &self.head; let mut current: &Option<Box<Node<T>>> = &self.head;
let mut result = String::new(); let mut result = String::new();
loop { loop {
match current { match current {
@ -62,7 +64,7 @@ impl fmt::Display for LinkedList {
} }
} }
impl Drop for LinkedList { impl<T> Drop for LinkedList<T> {
fn drop(&mut self) { fn drop(&mut self) {
let mut current = self.head.take(); let mut current = self.head.take();
while let Some(mut node) = current { while let Some(mut node) = current {
@ -71,5 +73,40 @@ impl Drop for LinkedList {
} }
} }
impl<T:Clone> Clone for Node<T> {
fn clone(&self) -> Self {
Node::new(self.value.clone(), self.next.clone())
}
}
impl<T:Clone> Clone for LinkedList<T> {
fn clone(&self) -> LinkedList<T> {
let mut copy_list = LinkedList::new();
copy_list.size = self.size;
copy_list.head = self.head.clone();
// tricky recursive clone, Option clone-> Box clone-> Node clone -> Node.next clone(Box clone)
// I tried to implement tail-insertion, but it is impossible to realize that without unsafe...
copy_list
}
}
impl<T:PartialEq> PartialEq for LinkedList<T> {
fn eq(&self, other: &Self) -> bool {
if self.size != other.size {
return false;
}
let mut ptr = & self.head;
let mut ptr_other = & other.head;
while let Some(node) = ptr {
// well, as their size are the same, it's fine to assume that they reach the end at the same time
let node_other = ptr_other.as_ref().unwrap();
if node_other.value != node.value {
return false;
}
ptr = &node.next;
ptr_other = &node_other.next;
}
true
}
}

View File

@ -15,6 +15,12 @@ fn main() {
println!("size: {}", list.get_size()); println!("size: {}", list.get_size());
println!("{}", list.to_string()); // ToString impl for anything impl Display println!("{}", list.to_string()); // ToString impl for anything impl Display
let mut list2 = list.clone();
println!("Right after clone: list == list2 ?= {}", list == list2);
list2.pop_front();
println!("list2.pop_front: {}", list2);
println!("list == list2 ?= {}", list == list2);
// If you implement iterator trait: // If you implement iterator trait:
//for val in &list { //for val in &list {
// println!("{}", val); // println!("{}", val);