# 链表 A linked list is also a `linear` data structure, and each element in the linked list is actually a separate object while all the objects are `linked together by the reference filed` in each element. In a `doubly linked list`, each node contains, besides the `next` node link, a second link field pointing to the `previous` node in the sequence. The two links may be called `next` and `prev`. And many modern operating systems use doubly linked lists to maintain references to active processes, threads and other dynamic objects. __Properties__ * Indexing O(n) * Insertion O(1) * Beginning O(1) * Middle (Indexing time+O(1)) * End O(n) * Deletion O(1) * Beginning O(1) * Middle (Indexing time+O(1)) * End O(n) * Search O(n) ```rust use std::fmt::{self, Display, Formatter}; use std::ptr::NonNull; struct Node { val: T, next: Option>>, prev: Option>>, } impl Node { fn new(t: T) -> Node { Node { val: t, prev: None, next: None, } } } pub struct LinkedList { length: u32, start: Option>>, end: Option>>, } impl Default for LinkedList { fn default() -> Self { Self::new() } } impl LinkedList { pub fn new() -> Self { Self { length: 0, start: None, end: None, } } pub fn add(&mut self, obj: T) { let mut node = Box::new(Node::new(obj)); // Since we are adding node at the end, next will always be None node.next = None; node.prev = self.end; // Get a pointer to node let node_ptr = Some(unsafe { NonNull::new_unchecked(Box::into_raw(node)) }); match self.end { // This is the case of empty list None => self.start = node_ptr, Some(end_ptr) => unsafe { (*end_ptr.as_ptr()).next = node_ptr }, } self.end = node_ptr; self.length += 1; } pub fn get(&mut self, index: i32) -> Option<&T> { self.get_ith_node(self.start, index) } fn get_ith_node(&mut self, node: Option>>, index: i32) -> Option<&T> { match node { None => None, Some(next_ptr) => match index { 0 => Some(unsafe { &(*next_ptr.as_ptr()).val }), _ => self.get_ith_node(unsafe { (*next_ptr.as_ptr()).next }, index - 1), }, } } } impl Display for LinkedList where T: Display, { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self.start { Some(node) => write!(f, "{}", unsafe { node.as_ref() }), None => Ok(()), } } } impl Display for Node where T: Display, { fn fmt(&self, f: &mut Formatter) -> fmt::Result { match self.next { Some(node) => write!(f, "{}, {}", self.val, unsafe { node.as_ref() }), None => write!(f, "{}", self.val), } } } #[cfg(test)] mod tests { use super::LinkedList; #[test] fn create_numeric_list() { let mut list = LinkedList::::new(); list.add(1); list.add(2); list.add(3); println!("Linked List is {}", list); assert_eq!(3, list.length); } #[test] fn create_string_list() { let mut list_str = LinkedList::::new(); list_str.add("A".to_string()); list_str.add("B".to_string()); list_str.add("C".to_string()); println!("Linked List is {}", list_str); assert_eq!(3, list_str.length); } #[test] fn get_by_index_in_numeric_list() { let mut list = LinkedList::::new(); list.add(1); list.add(2); println!("Linked List is {}", list); let retrived_item = list.get(1); assert!(retrived_item.is_some()); assert_eq!(2 as i32, *retrived_item.unwrap()); } #[test] fn get_by_index_in_string_list() { let mut list_str = LinkedList::::new(); list_str.add("A".to_string()); list_str.add("B".to_string()); println!("Linked List is {}", list_str); let retrived_item = list_str.get(1); assert!(retrived_item.is_some()); assert_eq!("B", *retrived_item.unwrap()); } } ```