evillatoro_data_structures/
linked_list.rs

1use std::fmt::Display;
2
3pub struct ListNode<T: Display> {
4    pub data: T,
5    pub next: Option<Box<ListNode<T>>>,
6}
7
8impl<T: Display> ListNode<T> {
9    pub fn new(value: T) -> ListNode<T> {
10        ListNode {
11            data: value,
12            next: None,
13        }
14    }
15
16    fn _to_string_debug(&self) -> String {
17        format!("[{:p}]", self)
18    }
19
20    fn to_string(&self) -> String {
21        format!("[{}]", self.data)
22    }
23}
24
25pub fn print<T: Display>(head: &ListNode<T>) {
26    let mut cur = Some(head);
27
28    while let Some(node) = cur {
29        print!("{} -> ", node.to_string());
30        cur = node.next.as_deref();
31    }
32    println!("None");
33}
34
35pub fn print_summary<T: Display>(head: &ListNode<T>) {
36    print(&head);
37    println!("Linked list length {len}", len = length(&head));
38}
39
40pub fn length<T: Display>(head: &ListNode<T>) -> i32 {
41    let mut cur = Some(head);
42    let mut count = 0;
43    while let Some(node) = cur {
44        count += 1;
45        cur = node.next.as_deref();
46    }
47    count
48}
49
50// Receives an option because the List could be empty
51pub fn insert_at_beginning<T: Display>(
52    head: Option<Box<ListNode<T>>>,
53    data: T,
54) -> Box<ListNode<T>> {
55    let mut new_node = Box::new(ListNode::new(data));
56
57    match head {
58        Some(node) => {
59            new_node.next = Some(node);
60            return new_node;
61        }
62        None => new_node,
63    }
64}
65
66pub fn insert_at_end<T: Display>(mut head: Option<Box<ListNode<T>>>, data: T) -> Box<ListNode<T>> {
67    let new_node = Box::new(ListNode::new(data));
68
69    match head {
70        Some(ref mut node) => {
71            let mut cur = node;
72            while let Some(ref mut temp) = cur.next {
73                cur = temp;
74            }
75            cur.next = Some(new_node);
76            return head.unwrap();
77        }
78        None => new_node,
79    }
80}
81
82pub fn insert_at_position<T: Display>(
83    mut head: Option<Box<ListNode<T>>>,
84    data: T,
85    pos: usize,
86) -> Box<ListNode<T>> {
87    if pos == 0 {
88        return insert_at_beginning(head, data);
89    }
90
91    let mut cur = &mut head;
92    let mut counter = 0;
93
94    while let Some(ref mut node) = *cur {
95        if counter == pos - 1 {
96            let mut new_node = ListNode::new(data);
97            new_node.next = node.next.take();
98            node.next = Some(Box::new(new_node));
99
100            return head.expect("head node must exist to insert at position");
101        }
102
103        counter += 1;
104        cur = &mut (*node).next;
105    }
106
107    return head.expect("head node must exist to insert at position");
108}
109
110// Returns the new head
111pub fn delete_first<T: Display>(head: Option<Box<ListNode<T>>>) -> Option<Box<ListNode<T>>> {
112    match head {
113        Some(first_node) => return first_node.next,
114        None => None,
115    }
116}
117
118pub fn delete_last<T: Display>(mut head: Option<Box<ListNode<T>>>) -> Option<Box<ListNode<T>>> {
119    match head {
120        Some(ref mut node) => {
121            let mut cur = node;
122
123            // Iterate until we find the second to last
124            while let Some(ref mut current) = (*cur).next {
125                let next = &current.next;
126                // 1 -> 2 -> 3 -> None
127                //      ^    ^
128                //   current |
129                //          next
130                if let Some(next) = next {
131                    if next.next.is_none() {
132                        (*current).next = None;
133                        return head;
134                    }
135                }
136                cur = current;
137            }
138            // next node does not exist, so we delete the head.
139            return None;
140        }
141        None => None,
142    }
143}
144
145pub fn delete_at_position<T: Display>(
146    mut head: Option<Box<ListNode<T>>>,
147    position: usize,
148) -> Option<Box<ListNode<T>>> {
149    if position == 0 {
150        return delete_first(head);
151    }
152
153    match head {
154        Some(ref mut node) => {
155            let mut cur = node;
156            let mut counter = 1;
157
158            // Iterate until we find the position
159            while let Some(ref mut current) = (*cur).next {
160                // i = 2
161                // 1 -> 2 -> 3 -> 4 -> None
162                //      ^    ^  ^
163                //   current |  |
164                //       remove |
165                //             next
166                if counter == position - 1 {
167                    if let Some(ref mut next) = current.next {
168                        (*current).next = (*next).next.take();
169                    }
170                    return head;
171                }
172                if counter >= position - 1 {
173                    break;
174                }
175                cur = current;
176                counter += 1;
177            }
178
179            return head;
180        }
181        None => None,
182    }
183}
184
185#[cfg(test)]
186mod tests {
187    use super::*;
188    #[test]
189    fn test_linked_list_to_string() {
190        println!("Test");
191        let head = insert_at_beginning::<i32>(None, 1);
192        let string = head.to_string();
193        assert!(!string.is_empty());
194        assert_eq!(string, "[1]");
195        assert_ne!(string, "[2]");
196    }
197
198    #[test]
199    fn test_print() {
200        let head = insert_at_beginning::<i32>(None, 1);
201        print(&head);
202        print_summary(&head);
203    }
204
205    #[test]
206    fn test_length() {
207        let mut head = insert_at_beginning::<i32>(None, 1);
208        head = insert_at_beginning(Some(head), 1);
209        head = insert_at_beginning(Some(head), 1);
210
211        assert_eq!(length(&head), 3);
212    }
213
214    #[test]
215    fn test_linked_list_to_string_debug() {
216        let head = insert_at_beginning::<i32>(None, 1);
217        let string = head._to_string_debug();
218        assert!(!string.is_empty());
219        assert_ne!(string, "[2]");
220    }
221
222    #[test]
223    fn test_insert_at_beggining() {
224        let head = insert_at_beginning::<i32>(None, 1);
225        assert_eq!((*head).data, 1);
226        assert!((*head).next.is_none());
227    }
228
229    #[test]
230    fn test_insert_at_incorrect() {
231        let head = insert_at_beginning::<i32>(None, 1);
232        assert_ne!((*head).data, 10);
233        assert!(!(*head).next.is_some());
234    }
235
236    #[test]
237    fn test_insert_at_beggining_existing_list() {
238        let mut head = insert_at_beginning::<i32>(None, 2);
239        head = insert_at_beginning(Some(head), 1);
240        // Data is correct
241        assert_eq!((*head).data, 1);
242        // Next node exists
243        assert!((*head).next.is_some());
244        // Next node's data is correct
245        let next_node = head.next.unwrap();
246        assert_eq!(next_node.data, 2);
247        // Next node points to None
248        assert!(next_node.next.is_none());
249    }
250
251    #[test]
252    fn test_insert_at_end() {
253        let mut head = insert_at_end::<i32>(None, 1);
254        assert_eq!((*head).data, 1);
255        assert!((*head).next.is_none());
256        head = insert_at_end(Some(head), 3);
257        head = insert_at_end(Some(head), 2);
258        assert_eq!((*head).data, 1);
259        assert!((*head).next.is_some());
260    }
261
262    #[test]
263    fn test_insert_at_position() {
264        let mut head = insert_at_position::<i32>(None, 1, 0);
265        assert_eq!((*head).data, 1);
266        assert!((*head).next.is_none());
267
268        let list_length = 29;
269
270        for i in 0..list_length - 2 {
271            head = insert_at_position(Some(head), i, 0);
272        }
273
274        let position = 15;
275        let value = 69;
276        head = insert_at_position(Some(head), 69, position);
277
278        let mut counter = 0;
279        let mut cur = &head;
280
281        while counter < position {
282            if let Some(ref node) = cur.next {
283                cur = &node;
284                counter += 1;
285            }
286        }
287        print_summary(&head);
288        assert_eq!(length(&head), list_length);
289        assert_eq!((*cur).data, value);
290    }
291
292    #[test]
293    #[should_panic]
294    fn test_insert_at_wrong_position() {
295        insert_at_position::<i32>(None, 1, 10);
296    }
297
298    #[test]
299    fn test_delete_first() {
300        let none = delete_first::<i32>(None);
301
302        assert!(none.is_none());
303
304        let mut head = insert_at_beginning::<i32>(None, 4);
305        // Retuns None if there is no more nodes
306        head = insert_at_beginning(Some(head), 3);
307        head = insert_at_beginning(Some(head), 2);
308        head = insert_at_beginning(Some(head), 1);
309
310        let new_head = delete_first::<i32>(Some(head));
311
312        assert!(new_head.is_some());
313
314        match new_head {
315            Some(node) => {
316                assert_eq!(2, node.data)
317            }
318            None => panic!("The new head should exist"),
319        }
320    }
321
322    #[test]
323    fn test_delete_last() {
324        let none = delete_last::<i32>(None);
325
326        assert!(none.is_none());
327
328        let mut list_length = 100;
329
330        let mut head = insert_at_beginning::<i32>(None, 69);
331
332        for i in 1..list_length {
333            head = insert_at_beginning(Some(head), i);
334        }
335        print_summary(&head);
336
337        head = delete_last(Some(head)).unwrap();
338        list_length -= 1;
339
340        let mut cur = &head;
341
342        while let Some(ref node) = (*cur).next {
343            cur = node;
344        }
345
346        assert_eq!(list_length, length(&head));
347        assert_eq!(1, (*cur).data);
348    }
349
350    #[test]
351    fn test_delete_last_single_node() {
352        let mut head = Some(insert_at_beginning::<i32>(None, 69));
353
354        head = delete_last(head);
355
356        assert!(head.is_none());
357    }
358
359    #[test]
360    fn test_delete_at_position() {
361        let list_length = 5;
362        let mut head = insert_at_beginning(None, list_length);
363
364        for i in 1..list_length {
365            head = insert_at_beginning(Some(head), list_length - i);
366        }
367
368        let delete_position = 2;
369        let mut counter = 0;
370
371        let original_data: i32;
372
373        {
374            let mut original_cur = &head;
375            while counter < delete_position {
376                if let Some(ref node) = original_cur.next {
377                    original_cur = &node;
378                    counter += 1;
379                }
380            }
381            original_data = (*original_cur).data;
382        }
383
384        head = delete_at_position(Some(head), delete_position).unwrap();
385
386        let mut counter = 0;
387        let mut cur = &head;
388
389        while counter < delete_position {
390            if let Some(ref node) = cur.next {
391                cur = &node;
392                counter += 1;
393            }
394        }
395        assert_ne!(original_data, (*cur).data);
396    }
397
398    #[test]
399    fn delete_at_position_fist_item() {
400        let mut head = insert_at_beginning(None, 1);
401        head = insert_at_beginning(Some(head), 0);
402
403        head = delete_at_position(Some(head), 0).unwrap();
404
405        assert_eq!(1, head.data);
406    }
407
408    #[test]
409    fn delete_at_position_out_of_bounds() {
410        let list_length = 5;
411        let mut head = insert_at_beginning::<i32>(None, list_length);
412
413        for i in 1..list_length {
414            head = insert_at_beginning(Some(head), list_length - i);
415        }
416
417        head = delete_at_position(Some(head), (list_length + 1000) as usize).unwrap();
418
419        // Should have not deleted something
420        assert_eq!(length(&head), list_length);
421    }
422
423    #[test]
424    fn delete_at_position_none_head() {
425        assert!(delete_at_position::<i32>(None, 100).is_none())
426    }
427}