You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
//! A single linked list implementation using safe Rust.use std::fmt::{Debug,Display,Formatter};typeLink<T> = Option<Box<Node<T>>>;#[derive(Debug)]structNode<T>{data:T,next:Link<T>,}impl<T>Node<T>{fnnew(data:T) -> Self{Self{ data,next:None}}}#[derive(Debug)]pubstructList<T>{head:Link<T>,}pubstructIntoIter<T>(List<T>);impl<T>IteratorforIntoIter<T>{typeItem = T;fnnext(&mutself) -> Option<Self::Item>{self.0.pop_front()}}impl<T>IntoIteratorforList<T>{typeItem = T;typeIntoIter = IntoIter<T>;fninto_iter(self) -> Self::IntoIter{IntoIter(self)}}impl<'node,T>IntoIteratorfor&'node List<T>{typeItem = &'node T;typeIntoIter = Iter<'node,T>;fninto_iter(self) -> Self::IntoIter{self.iter()}}impl<'node,T>IntoIteratorfor&'node mutList<T>{typeItem = &'node mutT;typeIntoIter = IterMut<'node,T>;fninto_iter(self) -> Self::IntoIter{self.iter_mut()}}impl<T>List<T>{/// Returns an empty Listpubfnnew() -> Self{List::default()}/// Returns an iterator over the list.pubfniter(&self) -> Iter<'_,T>{Iter{cursor:self.head.as_deref(),}}/// Returns an iterator that allows modifying each value.pubfniter_mut(&mutself) -> IterMut<'_,T>{IterMut{cursor:self.head.as_deref_mut(),}}/// Pushes an item to the end of the list.pubfnpush_back(&mutself,value:T){ifletSome(refmut head) = self.head{letmut last_node = head;whileletSome(refmut new_node) = last_node.next{
last_node = new_node;}
last_node.next = Some(Box::new(Node::new(value)));}else{self.head = Some(Box::new(Node::new(value)));}}/// Pushes an item to the front of the list.pubfnpush_front(&mutself,value:T){ifself.head.is_some(){let old_head = self.head.take();letmut new_head = Node::new(value);
new_head.next = old_head;self.head = Some(Box::new(new_head));}else{self.head = Some(Box::new(Node::new(value)));}}/// Removes the last element from the list and returns it, or None if it is empty.// The implementation of `pop_back()` depends on the situation of list and// can be divided into three cases:// 1. List is empty// 2. List has 1 node// 3. List has more than 1 nodepubfnpop_back(&mutself) -> Option<T>{// case 3: List has more than 1 nodeifself.head.is_some() && self.head.as_ref().unwrap().next.is_some(){letmut node_before_last_node = self.head.as_deref_mut().unwrap();// The impl in this branch is a bit awkward// See this question for more detail// https://stackoverflow.com/q/73789723/14092446while node_before_last_node.next.is_some(){if node_before_last_node.next.as_ref().unwrap().next.is_none(){break;}
node_before_last_node =
node_before_last_node.next.as_deref_mut().unwrap();}let last_node = node_before_last_node.next.take().unwrap();Some(last_node.data)}// case 2: List has 1 nodeelseifself.head.is_some()
&& self.head.as_ref().unwrap().next.is_none(){Some(self.head.take().unwrap().data)}// case 1: List is emptyelse{None}}/// Removes the first element from the list and returns it, or `None` if it is empty.pubfnpop_front(&mutself) -> Option<T>{self.head.take().map(|head| {self.head = head.next;
head.data})}/// Returns a reference to the first element in the List, or `None` if it is empty.pubfnpeek_front(&self) -> Option<&T>{self.head.as_ref().map(|head| &head.data)}/// Returns a reference to the last element in the List, or `None` if it is empty.pubfnpeek_back(&self) -> Option<&T>{ifletSome(ref head) = self.head{letmut last_node = head;whileletSome(ref next) = last_node.next{
last_node = next;}Some(&last_node.data)}else{None}}/// Returns a mutable reference to the first element in the List, or `None` if/// it is empty.pubfnpeek_mut_front(&mutself) -> Option<&mutT>{self.head.as_mut().map(|head| &mut head.data)}/// Returns a mutable reference to the last element in the List, or `None` if/// it is empty.pubfnpeek_mut_back(&mutself) -> Option<&mutT>{ifletSome(refmut head) = self.head{letmut last_node = head;whileletSome(refmut next) = last_node.next{
last_node = next;}Some(&mut last_node.data)}else{None}}/// Returns the length of the List.pubfnlen(&self) -> usize{letmut len = 0;letmut p = self.head.as_ref();whileletSome(p_non_null) = p {
len += 1;
p = p_non_null.next.as_ref();}
len
}/// Returns `true` if the list is empty. Otherwise, returns `false`.pubfnis_empty(&self) -> bool{self.len().eq(&0)}/// Sort the list.pubfnsort(&mutself){unimplemented!()}}/// An iterator over the references of the elements in a [`List`]pubstructIter<'node_lifetime,T>{cursor:Option<&'node_lifetime Node<T>>,}impl<'node_lifetime,T>IteratorforIter<'node_lifetime,T>{typeItem = &'node_lifetime T;fnnext(&mutself) -> Option<Self::Item>{self.cursor.map(|node| {self.cursor = node.next.as_deref();&node.data})}}/// An iterator over the mutable references of the elements in a [`List`]pubstructIterMut<'lifetime_of_node,T>{cursor:Option<&'lifetime_of_node mutNode<T>>,}impl<'node_lifetime,T>IteratorforIterMut<'node_lifetime,T>{typeItem = &'node_lifetime mutT;fnnext(&mutself) -> Option<Self::Item>{// ```rust// self.cursor.map(|node| {// self.cursor = node.next.as_deref_mut();// &mut node.data// })// ```// `self.cursor` is of type `Option<&mut Node<T>>`, which is not `Copy`.// `.map()` will move `self.cursor`, which is not allowed because `self.cursor`// is behind a shared reference `&mut self`.//// What if we call `.as_mut()` on `self.cursor` first//// ```rust// self.cursor.as_mut().map(|node| {// // tries to update `self.cursor` in this closure// self.cursor = node.next.as_deref_mut();// &mut node.data// })// ```// `.as_mut()` exclusively borrows `self.cursor` in this closure, and we// are trying to write to `self.cursor` in this closure, which is obviously// not safe, so Rust rejects this code.//// The accepted solution is to call `.take()` on `self.cursor` to takes its// value out of option. By doing this, we will have two separate objects in// the memory, one is `self.cursor`, which has the value `None`, another one// is a new object constructed by `.take()`, then we write to `self.cursor`// using the value from that new object, this is totally safe.self.cursor.take().map(|node| {self.cursor = node.next.as_deref_mut();&mut node.data})}}impl<T>DefaultforList<T>{fndefault() -> Self{Self{head:None}}}impl<T:Debug>DisplayforList<T>{fnfmt(&self,f:&mutFormatter<'_>) -> std::fmt::Result{write!(f, "List: ")?;letmut p = self.head.as_ref();whileletSome(p_not_null) = p {write!(f, "{:?} ", p_not_null.data)?;
p = p_not_null.next.as_ref();}Ok(())}}impl<T>FromIterator<T>forList<T>{fnfrom_iter<I>(iter:I) -> SelfwhereI:IntoIterator<Item = T>,{letmut list = Self::new();
iter.into_iter().for_each(|value| list.push_back(value));
list
}}impl<T>Extend<T>forList<T>{fnextend<I:IntoIterator<Item = T>>(&mutself,iter:I){
iter.into_iter().for_each(|value| self.push_back(value));}}#[cfg(test)]mod test {usesuper::*;#[test]fntest_from_iter(){let list = List::from_iter([1,2,3]);
list.into_iter().eq([1,2,3]);}#[test]fntest_extend(){letmut list = List::new();
list.extend([1,2,3]);
list.into_iter().eq([1,2,3]);letmut list = List::from_iter([1,2,3]);
list.extend([4,5,6]);
list.into_iter().eq([1,2,3,4,5,6]);}#[test]fntest_iter(){let list = List::from_iter([1,2,3]);
list.iter().eq([&1,&2,&3]);}#[test]fntest_iter_mut(){letmut list = List::from_iter([1,2,3]);
list.iter_mut().eq([&mut1,&mut2,&mut3]);}#[test]fntest_into_iter(){let list = List::from_iter([1,2,3]);
list.into_iter().eq([1,2,3]);}#[test]fntest_push_back(){letmut list = List::new();
list.push_back(1);
list.push_back(2);
list.push_back(3);
list.into_iter().eq([1,2,3]);}#[test]fntest_push_front(){letmut list = List::new();
list.push_front(1);
list.push_front(2);
list.push_front(3);
list.into_iter().eq([3,2,1]);}#[test]fntest_pop_back(){letmut list = List::from_iter([1,2,3]);assert_eq!(list.pop_back(), Some(3));assert_eq!(list.pop_back(), Some(2));assert_eq!(list.pop_back(), Some(1));assert_eq!(list.pop_back(), None);}#[test]fntest_pop_front(){letmut list = List::from_iter([1,2,3]);assert_eq!(list.pop_front(), Some(1));assert_eq!(list.pop_front(), Some(2));assert_eq!(list.pop_front(), Some(3));assert_eq!(list.pop_front(), None);}#[test]fntest_peek_front(){letmut list = List::new();assert_eq!(list.peek_front(), None);
list.push_front(1);assert_eq!(list.peek_front(), Some(&1));}#[test]fntest_peek_back(){letmut list = List::new();assert_eq!(list.peek_back(), None);
list.push_back(1);assert_eq!(list.peek_back(), Some(&1));
list.push_front(0);assert_eq!(list.peek_back(), Some(&1));
list.push_back(2);assert_eq!(list.peek_back(), Some(&2));}#[test]fntest_peek_mut_front(){letmut list = List::new();assert_eq!(list.peek_mut_front(), None);
list.push_front(1);assert_eq!(list.peek_mut_front(), Some(&mut1));}#[test]fntest_peek_mut_back(){letmut list = List::new();assert_eq!(list.peek_back(), None);
list.push_back(1);assert_eq!(list.peek_mut_back(), Some(&mut1));
list.push_front(0);assert_eq!(list.peek_mut_back(), Some(&mut1));
list.push_back(2);assert_eq!(list.peek_mut_back(), Some(&mut2));}#[test]fntest_len(){letmut list = List::new();assert_eq!(list.len(), 0);
list.push_back(0);assert_eq!(list.len(), 1);
list.extend([1,2,3]);assert_eq!(list.len(), 4);
list.pop_back();assert_eq!(list.len(), 3);}}
The text was updated successfully, but these errors were encountered:
The text was updated successfully, but these errors were encountered: