part 2 except iterator
This commit is contained in:
parent
bd5895814e
commit
1e4049204e
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user