From 5cb41a07f8e06dd441ca5c5eebd78e309461e912 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:02:14 +0300 Subject: [PATCH 01/16] Create queue_using_singly_linked_list.rs --- src/data_structures/queue_using_singly_linked_list.rs | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/data_structures/queue_using_singly_linked_list.rs diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -0,0 +1 @@ + From aa2909d422707db9c28efa5e5739e2d3bd6f2225 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:28:26 +0300 Subject: [PATCH 02/16] Created a queue using a singly linked list --- .../queue_using_singly_linked_list.rs | 343 ++++++++++++++++++ 1 file changed, 343 insertions(+) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index 8b137891791..174473724e1 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -1 +1,344 @@ +//! A queue implementation using a singly linked list +//! The queue follows FIFO (First-In First-Out) principle + +#![allow(unused)] + +use std::collections::VecDeque; +use std::fmt::Debug; +use std::marker::PhantomData; + +#[derive(Debug, Clone)] +struct Node { + element: T, + next: Option>>, +} + +impl Node { + fn new(element: T) -> Box { + Box::new(Self { + element, + next: None, + }) + } +} + +/// Queue Implementation using Singly Linked List logic +#[derive(Clone)] +struct Queue { + length: usize, + head: Option>>, + tail: Option>>, + // Act like we own the boxes or nodes, since we are gonna construct and mutate them + _marker: PhantomData>>, +} + +// Implementing default for our Queue +impl Default for Queue { + fn default() -> Self { + Queue::new() + } +} + +// Implement iterator for the queue +struct QueueIterator<'a, T> { + current: &'a Option>>, + _marker: PhantomData<&'a T> +} + +// Implementing Drop for Queue +impl Drop for Queue { + fn drop(&mut self) { + // Dequeue the queue until its empty + if let Some(_) = self.dequeue() {} + } +} + +// Debug implementation for our Queue +impl Debug for Queue where T: Debug + Clone { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut output = String::from("Queue ( elements: ["); + for elem in self.iter() { + output.push_str(&format!(" {:?} ", elem)); + } + + output.push_str(&format!("], length: {} )", self.len())); + + write!(f, "{}", output) + } +} + +// QueueIterator implementation +impl<'a, T: Debug + Clone> Iterator for QueueIterator<'a, T> { + type Item = &'a T; + + fn next(&mut self) -> Option { + // Initially, current is set to the current tail, + // It will walk the tail when a user calls next + self.current.as_ref().map(|node| { + self.current = &node.next; + + &node.element + }) + } +} + +// Implementation for the queue +impl Queue { + pub fn new() -> Self { + Self { + length: 0, + head: None, + tail: None, + _marker: PhantomData, + } + } + + // Iter function + pub fn iter(&self) -> QueueIterator<'_, T> { + QueueIterator { + current: &self.tail, + _marker: PhantomData + } + } + + /// The enqueue method, more of like the `push_back` of a linked list + pub fn enqueue(&mut self, element: T) where T: Clone { + // We create a new node + let mut new_node = Node::new(element); + // We make new_node's next to point to the old tail + new_node.next = self.tail.take(); + + // Here, we are setting the old_tail's next to point to the new pointer + if let Some(old_tail) = &mut self.tail { + old_tail.next = Some(Box::clone(&new_node)); + } + + // Making the new_node the tail + self.tail = Some(new_node.clone()); + + // If the list is empty, we first assign the new_node to the head before the tail + if self.head.is_none() { + self.head = Some(Box::clone(&new_node)); + } + + // Increment the length + self.length += 1; + } + + /// The `dequeue` method, more of like the `pop_front` method of a singly linked list + pub fn dequeue(&mut self) -> Option { + // We take the old head, and get next pointer the old head had been pointing to, we get that node, + // making it the new head + let result = self.head.take().map(|mut old_head| { + if let Some(next_node) = old_head.next.take() { + self.head = Some(next_node); + } + + if self.head.is_none() { + self.tail = None; + + // When the head is popped, the element is none, meaning + // it will not decrement length + // Check whether the length is zero, then the list is empty, so it will skip, else + // decrement 1 from the length + if !self.is_empty() { + self.length -= 1; + } + } + + old_head.element + }); + + // If the list wasn't empty (or popped a node), decrement the length + // SAFETY: this will prevent the length from going below usize::MIN, because + // a user may try to dequeue an empty queue, which would lead to negatives + // which are not supported by the usize + if result.is_some() { + self.length -= 1; + } + + result + } + + /// Reference to the first element in the queue + pub fn peek_front(&self) -> Option<&T> { + self.head.as_ref().map(|head| &head.element) + } + + // Reference to value at the end of the queue + pub fn peek_back(&self) -> Option<&T> { + self.tail.as_ref().map(|tail| &tail.element) + } + + // Get element by index from the queue + pub fn get(&self, index: usize) -> Option<&T> { + let mut counter = 0; + let mut current = &self.head; + + // If index == 0, it returns the first element from the queue, using the peek_front + if index == 0 { + return self.peek_front(); + + // if index is the last, then returns last element using peek_back + } else if index == (self.len() - 1) { + return self.peek_back(); + + // Else, returns none, if index is out of bounds + } else if index > (self.len() - 1) { + return None; + } + + let mut get_node: Option<&T> = None; + + // If the node was not got we also index through the tail + if get_node.is_none() { + // Setting current to now be the tail + current = &self.tail; + // And also reset counter to 0, because the head will have atmost 1 element + counter += 1; + + while let Some(node) = ¤t { + if counter == index { + get_node = Some(&(*node).element); + } + + // Increment counter + counter += 1; + + current = &node.next; + } + } + + get_node + } + + /// Insert element at nth position in the queue + pub fn insert(&mut self, index: usize, element: T) where T: Clone { + let mut counter = 0; + // Initialize a new node + let mut new_node = Node::new(element.clone()); + + // If the index is greater the last index, then panic + if self.len() - 1 < index { + panic!("Trying to insert element to index out of bounds") + } + + // If the length is zero, then just insert at the tail + if self.len() == 0 { + self.tail = Some(Box::clone(&new_node)); + } else { + // If length is greater than zero, we assign current to zero, initially + let mut current = self.tail.as_mut().unwrap(); + + // Create a for loop to end at the index selected by user, then assign + // the node at that index to current + // I made it (index - 1) so that it gets the previous node instead of the exact + // node inorder for current.next to point to the exact node, when it reaches the node + for _ in 0..index - 1 { + current = current.next.as_mut().unwrap(); + } + + // We set the new_node's next to be current next node + new_node.next = current.next.clone(); + // Then we set the current's next node to point to the new_node + current.next = Some(new_node); + } + } + + /// Gets the length of the queue + pub fn len(&self) -> usize { + self.length + } + + pub fn is_empty(&self) -> bool { + self.length == 0 + } +} + + +mod tests { + use crate::Queue; + + #[test] + fn test_enqueue() { + // Creating a new queue + let mut queue = Queue::::new(); + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + assert_eq!(queue.len(), 3); + } + + #[test] + fn test_dequeue() { + let mut queue = Queue::::new(); + // Enqueue a couple of values + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + queue.enqueue(4); + + // Then dequeue some values + queue.dequeue(); + queue.dequeue(); + + assert_eq!(queue.len(), 2); + } + + #[test] + fn test_queue_length() { + use std::collections::VecDeque; + let mut queue = Queue::new(); + + // Enqueue a couple of elements + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + assert_eq!(queue.len(), 3); + } + + #[test] + fn test_get_from_queue() { + let mut queue = Queue::new(); + + queue.enqueue(2); + queue.enqueue(3); + queue.enqueue(5); + + let result = queue.get(1); + println!("{:#?}", result); + + assert!(result.is_some()); + } + + #[test] + fn test_queue_insert() { + let mut queue = Queue::default(); + + queue.enqueue(1); + queue.enqueue(3); + queue.enqueue(4); + queue.insert(2, 2); + + assert_eq!(queue.len(), 4); + } + + #[test] + fn queue_iter() { + let mut queue = Queue::::new(); + queue.enqueue(2); + queue.enqueue(3); + queue.enqueue(4); + + println!("{:?}", queue); + + for i in queue.iter() { + println!("Item: {}", i); + } + + assert!(true); + } +} From d744c93facaf85dd8eaef8901a0c82ac42248e17 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Wed, 9 Oct 2024 22:31:13 +0300 Subject: [PATCH 03/16] Update queue_using_singly_linked_list.rs Fixed incrementing length in the insert method of the Queue --- src/data_structures/queue_using_singly_linked_list.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index 174473724e1..60a3a726fdb 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -241,8 +241,12 @@ impl Queue { // We set the new_node's next to be current next node new_node.next = current.next.clone(); + // Then we set the current's next node to point to the new_node current.next = Some(new_node); + + // Increment the length + self.length += 1; } } From 61c55a4538ecf90666f8c58463c061d4a9384b8e Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 09:39:42 +0300 Subject: [PATCH 04/16] Added delete method to our queue --- .../queue_using_singly_linked_list.rs | 125 +++++++++++++++--- 1 file changed, 107 insertions(+), 18 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index 60a3a726fdb..cffa220a1e4 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -1,14 +1,21 @@ - //! A queue implementation using a singly linked list //! The queue follows FIFO (First-In First-Out) principle +//! The [enqueue] method's time complexity is O(1) +//! The [dequeue] method's time complexity is O(1) +//! The [insert] method's time complexity is O(n) +//! The [delete] method's time complexity is O(n) +//! The [peek_front] method's time complexity is O(1) +//! The [peek_back] method's time complexity is O(1) +//! The [len] method's time complexity is O(1) +//! The [is_empty] method's time complexity is O(1) +//! +//! I implemented Iterator, Default and Debug trait for our Queue data structure +//! -#![allow(unused)] - -use std::collections::VecDeque; use std::fmt::Debug; use std::marker::PhantomData; -#[derive(Debug, Clone)] +#[derive(Clone)] struct Node { element: T, next: Option>>, @@ -55,7 +62,7 @@ impl Drop for Queue { } // Debug implementation for our Queue -impl Debug for Queue where T: Debug + Clone { +impl Debug for Queue where T: Debug { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut output = String::from("Queue ( elements: ["); for elem in self.iter() { @@ -69,7 +76,7 @@ impl Debug for Queue where T: Debug + Clone { } // QueueIterator implementation -impl<'a, T: Debug + Clone> Iterator for QueueIterator<'a, T> { +impl<'a, T> Iterator for QueueIterator<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { @@ -94,7 +101,7 @@ impl Queue { } } - // Iter function + // Iter method, will enably us to iterate through our queue pub fn iter(&self) -> QueueIterator<'_, T> { QueueIterator { current: &self.tail, @@ -130,13 +137,13 @@ impl Queue { pub fn dequeue(&mut self) -> Option { // We take the old head, and get next pointer the old head had been pointing to, we get that node, // making it the new head - let result = self.head.take().map(|mut old_head| { - if let Some(next_node) = old_head.next.take() { - self.head = Some(next_node); + let result = self.tail.take().map(|mut old_tail| { + if let Some(next_node) = old_tail.next.take() { + self.tail = Some(next_node); } - if self.head.is_none() { - self.tail = None; + if self.tail.is_none() { + self.head = None; // When the head is popped, the element is none, meaning // it will not decrement length @@ -147,7 +154,7 @@ impl Queue { } } - old_head.element + old_tail.element }); // If the list wasn't empty (or popped a node), decrement the length @@ -198,9 +205,14 @@ impl Queue { // And also reset counter to 0, because the head will have atmost 1 element counter += 1; + // We traverse to the node to get from the queue while let Some(node) = ¤t { + // If the selected index matches the pointer, then set get_node + // to node at that index if counter == index { get_node = Some(&(*node).element); + // Break the loop after getting the element at given index + break; } // Increment counter @@ -241,12 +253,49 @@ impl Queue { // We set the new_node's next to be current next node new_node.next = current.next.clone(); - - // Then we set the current's next node to point to the new_node - current.next = Some(new_node); // Increment the length self.length += 1; + // Then we set the current's next node to point to the new_node + current.next = Some(new_node); + } + } + + pub fn delete(&mut self, index: usize) -> Option where T: Clone { + // Index out of bounds + if index >= self.length { + return None; + } + + if index == 0 { + // Deleting the head (equivalent to dequeue) + let deleted_node = self.dequeue(); + return deleted_node; + } else { + let mut current = self.tail.as_mut()?; + + // Traverse to the node just before the one to delete + for _ in 0..index - 1 { + current = current.next.as_mut()?; + } + + // The node to delete is current.next + let mut to_delete = current.next.take()?; // Take ownership of the node to delete + + // Re-link the current node to skip over the deleted node + current.next = to_delete.next.take(); + + // If the deleted node was the last node, update the tail pointer + if current.next.is_none() { + // If there is no next node, set tail to the current node + self.tail = Some(current.clone()); + } + + // Decrease the queue length + self.length -= 1; + + // Return the deleted element + Some(to_delete.element) } } @@ -255,12 +304,14 @@ impl Queue { self.length } + /// Check whether the queue is empty or not pub fn is_empty(&self) -> bool { self.length == 0 } } +/// The queue implementation tests mod tests { use crate::Queue; @@ -293,7 +344,6 @@ mod tests { #[test] fn test_queue_length() { - use std::collections::VecDeque; let mut queue = Queue::new(); // Enqueue a couple of elements @@ -304,6 +354,28 @@ mod tests { assert_eq!(queue.len(), 3); } + #[test] + fn test_peek_front() { + let mut queue = Queue::default(); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + assert_eq!(Some(&3), queue.peek_front()); + } + + #[test] + fn peek_back() { + let mut queue = Queue::default(); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + assert_eq!(Some(&1), queue.peek_back()); + } + #[test] fn test_get_from_queue() { let mut queue = Queue::new(); @@ -345,4 +417,21 @@ mod tests { assert!(true); } + + #[test] + fn test_queue_delete() { + let mut queue = Queue::default(); + + queue.enqueue(1); + queue.enqueue(2); + queue.enqueue(3); + + queue.delete(1); + + assert!(false); + assert_eq!(queue.len(), 1); + + // Whether to see whether an option of variant Some is returned + assert!(queue.delete(1).is_some()); + } } From f8d0b55cfc9fc93e9d8b65410fe69338d18618c6 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 09:43:51 +0300 Subject: [PATCH 05/16] Formatted the code using cargo fmt --- .../queue_using_singly_linked_list.rs | 111 ++++++++++-------- 1 file changed, 62 insertions(+), 49 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index cffa220a1e4..eb63dd2f353 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -1,16 +1,16 @@ //! A queue implementation using a singly linked list //! The queue follows FIFO (First-In First-Out) principle -//! The [enqueue] method's time complexity is O(1) -//! The [dequeue] method's time complexity is O(1) -//! The [insert] method's time complexity is O(n) -//! The [delete] method's time complexity is O(n) -//! The [peek_front] method's time complexity is O(1) -//! The [peek_back] method's time complexity is O(1) -//! The [len] method's time complexity is O(1) -//! The [is_empty] method's time complexity is O(1) -//! +//! The [enqueue] method's time complexity is O(1) +//! The [dequeue] method's time complexity is O(1) +//! The [insert] method's time complexity is O(n) +//! The [delete] method's time complexity is O(n) +//! The [peek_front] method's time complexity is O(1) +//! The [peek_back] method's time complexity is O(1) +//! The [len] method's time complexity is O(1) +//! The [is_empty] method's time complexity is O(1) +//! //! I implemented Iterator, Default and Debug trait for our Queue data structure -//! +//! use std::fmt::Debug; use std::marker::PhantomData; @@ -49,8 +49,8 @@ impl Default for Queue { // Implement iterator for the queue struct QueueIterator<'a, T> { - current: &'a Option>>, - _marker: PhantomData<&'a T> + current: &'a Option>>, + _marker: PhantomData<&'a T>, } // Implementing Drop for Queue @@ -62,14 +62,17 @@ impl Drop for Queue { } // Debug implementation for our Queue -impl Debug for Queue where T: Debug { +impl Debug for Queue +where + T: Debug, +{ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut output = String::from("Queue ( elements: ["); for elem in self.iter() { output.push_str(&format!(" {:?} ", elem)); } - output.push_str(&format!("], length: {} )", self.len())); + output.push_str(&format!("], length: {} )", self.len())); write!(f, "{}", output) } @@ -77,13 +80,13 @@ impl Debug for Queue where T: Debug { // QueueIterator implementation impl<'a, T> Iterator for QueueIterator<'a, T> { - type Item = &'a T; + type Item = &'a T; fn next(&mut self) -> Option { - // Initially, current is set to the current tail, + // Initially, current is set to the current tail, // It will walk the tail when a user calls next self.current.as_ref().map(|node| { - self.current = &node.next; + self.current = &node.next; &node.element }) @@ -104,13 +107,16 @@ impl Queue { // Iter method, will enably us to iterate through our queue pub fn iter(&self) -> QueueIterator<'_, T> { QueueIterator { - current: &self.tail, - _marker: PhantomData + current: &self.tail, + _marker: PhantomData, } } /// The enqueue method, more of like the `push_back` of a linked list - pub fn enqueue(&mut self, element: T) where T: Clone { + pub fn enqueue(&mut self, element: T) + where + T: Clone, + { // We create a new node let mut new_node = Node::new(element); // We make new_node's next to point to the old tail @@ -205,14 +211,14 @@ impl Queue { // And also reset counter to 0, because the head will have atmost 1 element counter += 1; - // We traverse to the node to get from the queue + // We traverse to the node to get from the queue while let Some(node) = ¤t { - // If the selected index matches the pointer, then set get_node + // If the selected index matches the pointer, then set get_node // to node at that index if counter == index { get_node = Some(&(*node).element); // Break the loop after getting the element at given index - break; + break; } // Increment counter @@ -225,10 +231,13 @@ impl Queue { get_node } - /// Insert element at nth position in the queue - pub fn insert(&mut self, index: usize, element: T) where T: Clone { + /// Insert element at nth position in the queue + pub fn insert(&mut self, index: usize, element: T) + where + T: Clone, + { let mut counter = 0; - // Initialize a new node + // Initialize a new node let mut new_node = Node::new(element.clone()); // If the index is greater the last index, then panic @@ -241,11 +250,11 @@ impl Queue { self.tail = Some(Box::clone(&new_node)); } else { // If length is greater than zero, we assign current to zero, initially - let mut current = self.tail.as_mut().unwrap(); + let mut current = self.tail.as_mut().unwrap(); - // Create a for loop to end at the index selected by user, then assign + // Create a for loop to end at the index selected by user, then assign // the node at that index to current - // I made it (index - 1) so that it gets the previous node instead of the exact + // I made it (index - 1) so that it gets the previous node instead of the exact // node inorder for current.next to point to the exact node, when it reaches the node for _ in 0..index - 1 { current = current.next.as_mut().unwrap(); @@ -261,39 +270,42 @@ impl Queue { } } - pub fn delete(&mut self, index: usize) -> Option where T: Clone { + pub fn delete(&mut self, index: usize) -> Option + where + T: Clone, + { // Index out of bounds if index >= self.length { - return None; + return None; } - + if index == 0 { // Deleting the head (equivalent to dequeue) let deleted_node = self.dequeue(); return deleted_node; } else { let mut current = self.tail.as_mut()?; - + // Traverse to the node just before the one to delete for _ in 0..index - 1 { current = current.next.as_mut()?; } - + // The node to delete is current.next let mut to_delete = current.next.take()?; // Take ownership of the node to delete - + // Re-link the current node to skip over the deleted node current.next = to_delete.next.take(); - + // If the deleted node was the last node, update the tail pointer if current.next.is_none() { // If there is no next node, set tail to the current node self.tail = Some(current.clone()); } - + // Decrease the queue length self.length -= 1; - + // Return the deleted element Some(to_delete.element) } @@ -304,13 +316,12 @@ impl Queue { self.length } - /// Check whether the queue is empty or not + /// Check whether the queue is empty or not pub fn is_empty(&self) -> bool { self.length == 0 } } - /// The queue implementation tests mod tests { use crate::Queue; @@ -356,7 +367,7 @@ mod tests { #[test] fn test_peek_front() { - let mut queue = Queue::default(); + let mut queue = Queue::default(); queue.enqueue(1); queue.enqueue(2); @@ -365,9 +376,9 @@ mod tests { assert_eq!(Some(&3), queue.peek_front()); } - #[test] + #[test] fn peek_back() { - let mut queue = Queue::default(); + let mut queue = Queue::default(); queue.enqueue(1); queue.enqueue(2); @@ -404,15 +415,15 @@ mod tests { #[test] fn queue_iter() { - let mut queue = Queue::::new(); + let mut queue = Queue::::new(); queue.enqueue(2); queue.enqueue(3); queue.enqueue(4); - println!("{:?}", queue); - + println!("{:?}", queue); + for i in queue.iter() { - println!("Item: {}", i); + println!("Item: {}", i); } assert!(true); @@ -420,14 +431,14 @@ mod tests { #[test] fn test_queue_delete() { - let mut queue = Queue::default(); + let mut queue = Queue::default(); queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); queue.delete(1); - + assert!(false); assert_eq!(queue.len(), 1); @@ -435,3 +446,5 @@ mod tests { assert!(queue.delete(1).is_some()); } } + +fn main() {} From e0fafbdee1f1a4ab644d268aecb5895f9623b57c Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 09:56:32 +0300 Subject: [PATCH 06/16] Ran cargo fmt and clippy --- .../queue_using_singly_linked_list.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index eb63dd2f353..62014d9f127 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -57,7 +57,7 @@ struct QueueIterator<'a, T> { impl Drop for Queue { fn drop(&mut self) { // Dequeue the queue until its empty - if let Some(_) = self.dequeue() {} + while self.dequeue().is_some() {} } } @@ -216,7 +216,7 @@ impl Queue { // If the selected index matches the pointer, then set get_node // to node at that index if counter == index { - get_node = Some(&(*node).element); + get_node = Some(&node.element); // Break the loop after getting the element at given index break; } @@ -236,7 +236,6 @@ impl Queue { where T: Clone, { - let mut counter = 0; // Initialize a new node let mut new_node = Node::new(element.clone()); @@ -246,7 +245,7 @@ impl Queue { } // If the length is zero, then just insert at the tail - if self.len() == 0 { + if self.is_empty() { self.tail = Some(Box::clone(&new_node)); } else { // If length is greater than zero, we assign current to zero, initially @@ -282,7 +281,7 @@ impl Queue { if index == 0 { // Deleting the head (equivalent to dequeue) let deleted_node = self.dequeue(); - return deleted_node; + deleted_node } else { let mut current = self.tail.as_mut()?; @@ -324,7 +323,7 @@ impl Queue { /// The queue implementation tests mod tests { - use crate::Queue; + use super::*; #[test] fn test_enqueue() { @@ -446,5 +445,3 @@ mod tests { assert!(queue.delete(1).is_some()); } } - -fn main() {} From db0020e64920cc85051b786b21b0c669219843ee Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:05:15 +0300 Subject: [PATCH 07/16] Ran cargo test and clippy again --- src/data_structures/queue_using_singly_linked_list.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index 62014d9f127..c6763310eaf 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -280,8 +280,7 @@ impl Queue { if index == 0 { // Deleting the head (equivalent to dequeue) - let deleted_node = self.dequeue(); - deleted_node + self.dequeue() } else { let mut current = self.tail.as_mut()?; @@ -322,6 +321,7 @@ impl Queue { } /// The queue implementation tests +#[cfg(test)] mod tests { use super::*; From 2bab0a42160a6638d505f210f6b8a9298c34e2e8 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:07:16 +0300 Subject: [PATCH 08/16] Adding the Queue to the module tree --- src/data_structures/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/data_structures/mod.rs b/src/data_structures/mod.rs index 621ff290360..d3fb038cca5 100644 --- a/src/data_structures/mod.rs +++ b/src/data_structures/mod.rs @@ -19,6 +19,7 @@ mod treap; mod trie; mod union_find; mod veb_tree; +mod queue_using_singly_linked_list; pub use self::avl_tree::AVLTree; pub use self::b_tree::BTree; @@ -43,3 +44,4 @@ pub use self::treap::Treap; pub use self::trie::Trie; pub use self::union_find::UnionFind; pub use self::veb_tree::VebTree; +pub use self::queue_using_singly_linked_list::Queue; From 0b11157a0f4f5959803f0a72662514051e4bf657 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:10:42 +0300 Subject: [PATCH 09/16] Adding link to the Queue in data structures dir --- DIRECTORY.md | 1 + 1 file changed, 1 insertion(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index 1dd188f69a8..7a7b8968b7a 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -66,6 +66,7 @@ * [Heap](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/heap.rs) * [Lazy Segment Tree](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/lazy_segment_tree.rs) * [Linked List](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/linked_list.rs) + * [Queue](https://github.com/Ismael144/Rust-algorithms/blob/master/src/data_structures/queue_using_singly_linked_list.rs) * Probabilistic * [Bloom Filter](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/probabilistic/bloom_filter.rs) * [Count Min Sketch](https://github.com/TheAlgorithms/Rust/blob/master/src/data_structures/probabilistic/count_min_sketch.rs) From bb3de5705bfe4a9874704dab52a04671b84d657a Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:46:13 +0300 Subject: [PATCH 10/16] Making sure all tests run --- .../queue_using_singly_linked_list.rs | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index c6763310eaf..a62884f66bd 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + //! A queue implementation using a singly linked list //! The queue follows FIFO (First-In First-Out) principle //! The [enqueue] method's time complexity is O(1) @@ -167,7 +169,7 @@ impl Queue { // SAFETY: this will prevent the length from going below usize::MIN, because // a user may try to dequeue an empty queue, which would lead to negatives // which are not supported by the usize - if result.is_some() { + if result.is_some() && !self.is_empty() { self.length -= 1; } @@ -176,19 +178,18 @@ impl Queue { /// Reference to the first element in the queue pub fn peek_front(&self) -> Option<&T> { - self.head.as_ref().map(|head| &head.element) + self.tail.as_ref().map(|tail| &tail.element) } // Reference to value at the end of the queue pub fn peek_back(&self) -> Option<&T> { - self.tail.as_ref().map(|tail| &tail.element) + self.head.as_ref().map(|head| &head.element) } // Get element by index from the queue pub fn get(&self, index: usize) -> Option<&T> { let mut counter = 0; - let mut current = &self.head; - + // If index == 0, it returns the first element from the queue, using the peek_front if index == 0 { return self.peek_front(); @@ -197,22 +198,24 @@ impl Queue { } else if index == (self.len() - 1) { return self.peek_back(); - // Else, returns none, if index is out of bounds + // Else, returns none, if index is out of bounds } else if index > (self.len() - 1) { return None; } + let mut _current = &self.head; + let mut get_node: Option<&T> = None; - + // If the node was not got we also index through the tail if get_node.is_none() { // Setting current to now be the tail - current = &self.tail; + _current = &self.tail; // And also reset counter to 0, because the head will have atmost 1 element counter += 1; // We traverse to the node to get from the queue - while let Some(node) = ¤t { + while let Some(node) = &_current { // If the selected index matches the pointer, then set get_node // to node at that index if counter == index { @@ -224,7 +227,7 @@ impl Queue { // Increment counter counter += 1; - current = &node.next; + _current = &node.next; } } @@ -333,6 +336,9 @@ mod tests { queue.enqueue(2); queue.enqueue(3); + println!("{:?}", queue); + println!("{:?}", queue.len()); + assert_eq!(queue.len(), 3); } @@ -438,9 +444,7 @@ mod tests { queue.delete(1); - assert!(false); - assert_eq!(queue.len(), 1); - + assert_eq!(queue.len(), 2); // Whether to see whether an option of variant Some is returned assert!(queue.delete(1).is_some()); } From 2a3b45e178d5b1d6d9e1cf902108edce00a54e8a Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:51:58 +0300 Subject: [PATCH 11/16] Making sure all checks succeed --- src/data_structures/queue_using_singly_linked_list.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index a62884f66bd..3371c539a20 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -34,7 +34,7 @@ impl Node { /// Queue Implementation using Singly Linked List logic #[derive(Clone)] -struct Queue { +pub struct Queue { length: usize, head: Option>>, tail: Option>>, @@ -189,7 +189,6 @@ impl Queue { // Get element by index from the queue pub fn get(&self, index: usize) -> Option<&T> { let mut counter = 0; - // If index == 0, it returns the first element from the queue, using the peek_front if index == 0 { return self.peek_front(); @@ -204,9 +203,7 @@ impl Queue { } let mut _current = &self.head; - let mut get_node: Option<&T> = None; - // If the node was not got we also index through the tail if get_node.is_none() { // Setting current to now be the tail From 2a7d502b937f6700703a048d2ed9abe8c0dc5944 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:54:29 +0300 Subject: [PATCH 12/16] Changing Queue to LinkedListQueue due to conflicts --- src/data_structures/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/mod.rs b/src/data_structures/mod.rs index d3fb038cca5..ff2af9d08ec 100644 --- a/src/data_structures/mod.rs +++ b/src/data_structures/mod.rs @@ -44,4 +44,4 @@ pub use self::treap::Treap; pub use self::trie::Trie; pub use self::union_find::UnionFind; pub use self::veb_tree::VebTree; -pub use self::queue_using_singly_linked_list::Queue; +pub use self::queue_using_singly_linked_list::LinkedListQueue; From 86d87d0f81aa9b5ea66cbe4983b72ddb53613639 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:00:29 +0300 Subject: [PATCH 13/16] Wrong import --- src/data_structures/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/mod.rs b/src/data_structures/mod.rs index ff2af9d08ec..94fc1298a25 100644 --- a/src/data_structures/mod.rs +++ b/src/data_structures/mod.rs @@ -44,4 +44,4 @@ pub use self::treap::Treap; pub use self::trie::Trie; pub use self::union_find::UnionFind; pub use self::veb_tree::VebTree; -pub use self::queue_using_singly_linked_list::LinkedListQueue; +pub use self::queue_using_singly_linked_list::Queue as LinkedListQueue; From 9d34aa39a189eadf9907f89ff396299571ce1532 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:46:20 +0300 Subject: [PATCH 14/16] Update queue_using_singly_linked_list.rs --- .../queue_using_singly_linked_list.rs | 77 ++++++++----------- 1 file changed, 32 insertions(+), 45 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index 3371c539a20..ee8917ade16 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -11,7 +11,7 @@ //! The [len] method's time complexity is O(1) //! The [is_empty] method's time complexity is O(1) //! -//! I implemented Iterator, Default and Debug trait for our Queue data structure +//! I implemented Iterator, Default and Debug trait for our LinkedListQueue data structure //! use std::fmt::Debug; @@ -32,9 +32,9 @@ impl Node { } } -/// Queue Implementation using Singly Linked List logic +/// LinkedListQueue Implementation using Singly Linked List logic #[derive(Clone)] -pub struct Queue { +pub struct LinkedListQueue { length: usize, head: Option>>, tail: Option>>, @@ -42,46 +42,49 @@ pub struct Queue { _marker: PhantomData>>, } -// Implementing default for our Queue -impl Default for Queue { +// Implementing default for our LinkedListQueue +impl Default for LinkedListQueue { fn default() -> Self { - Queue::new() + LinkedListQueue::new() } } // Implement iterator for the queue -struct QueueIterator<'a, T> { +pub struct LinkedListQueueIterator<'a, T> { current: &'a Option>>, _marker: PhantomData<&'a T>, } -// Implementing Drop for Queue -impl Drop for Queue { +// Implementing Drop for LinkedListQueue +impl Drop for LinkedListQueue { fn drop(&mut self) { // Dequeue the queue until its empty while self.dequeue().is_some() {} } } -// Debug implementation for our Queue -impl Debug for Queue +// Debug implementation for our LinkedListQueue +impl Debug for LinkedListQueue where T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut output = String::from("Queue ( elements: ["); + use std::fmt::Write as _; + + let mut output = String::from("LinkedListQueue ( elements: ["); + for elem in self.iter() { - output.push_str(&format!(" {:?} ", elem)); + let _ = write!(output, " {:?} ", elem); } + + let _ = write!(output, "], length: {} )", self.len()); - output.push_str(&format!("], length: {} )", self.len())); - - write!(f, "{}", output) + write!(f, "{}", output) } } -// QueueIterator implementation -impl<'a, T> Iterator for QueueIterator<'a, T> { +// LinkedListQueueIterator implementation +impl<'a, T> Iterator for LinkedListQueueIterator<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { @@ -96,7 +99,7 @@ impl<'a, T> Iterator for QueueIterator<'a, T> { } // Implementation for the queue -impl Queue { +impl LinkedListQueue { pub fn new() -> Self { Self { length: 0, @@ -107,8 +110,8 @@ impl Queue { } // Iter method, will enably us to iterate through our queue - pub fn iter(&self) -> QueueIterator<'_, T> { - QueueIterator { + pub fn iter(&self) -> LinkedListQueueIterator<'_, T> { + LinkedListQueueIterator { current: &self.tail, _marker: PhantomData, } @@ -328,7 +331,7 @@ mod tests { #[test] fn test_enqueue() { // Creating a new queue - let mut queue = Queue::::new(); + let mut queue = LinkedListQueue::::new(); queue.enqueue(1); queue.enqueue(2); queue.enqueue(3); @@ -341,7 +344,7 @@ mod tests { #[test] fn test_dequeue() { - let mut queue = Queue::::new(); + let mut queue = LinkedListQueue::::new(); // Enqueue a couple of values queue.enqueue(1); queue.enqueue(2); @@ -357,7 +360,7 @@ mod tests { #[test] fn test_queue_length() { - let mut queue = Queue::new(); + let mut queue = LinkedListQueue::new(); // Enqueue a couple of elements queue.enqueue(1); @@ -369,7 +372,7 @@ mod tests { #[test] fn test_peek_front() { - let mut queue = Queue::default(); + let mut queue = LinkedListQueue::default(); queue.enqueue(1); queue.enqueue(2); @@ -380,7 +383,7 @@ mod tests { #[test] fn peek_back() { - let mut queue = Queue::default(); + let mut queue = LinkedListQueue::default(); queue.enqueue(1); queue.enqueue(2); @@ -391,7 +394,7 @@ mod tests { #[test] fn test_get_from_queue() { - let mut queue = Queue::new(); + let mut queue = LinkedListQueue::new(); queue.enqueue(2); queue.enqueue(3); @@ -405,7 +408,7 @@ mod tests { #[test] fn test_queue_insert() { - let mut queue = Queue::default(); + let mut queue = LinkedListQueue::default(); queue.enqueue(1); queue.enqueue(3); @@ -415,25 +418,9 @@ mod tests { assert_eq!(queue.len(), 4); } - #[test] - fn queue_iter() { - let mut queue = Queue::::new(); - queue.enqueue(2); - queue.enqueue(3); - queue.enqueue(4); - - println!("{:?}", queue); - - for i in queue.iter() { - println!("Item: {}", i); - } - - assert!(true); - } - #[test] fn test_queue_delete() { - let mut queue = Queue::default(); + let mut queue = LinkedListQueue::default(); queue.enqueue(1); queue.enqueue(2); From 19c36774feb7a246f45dedc8e81f4b4e86ff85a2 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:47:32 +0300 Subject: [PATCH 15/16] Update mod.rs --- src/data_structures/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data_structures/mod.rs b/src/data_structures/mod.rs index 94fc1298a25..ff2af9d08ec 100644 --- a/src/data_structures/mod.rs +++ b/src/data_structures/mod.rs @@ -44,4 +44,4 @@ pub use self::treap::Treap; pub use self::trie::Trie; pub use self::union_find::UnionFind; pub use self::veb_tree::VebTree; -pub use self::queue_using_singly_linked_list::Queue as LinkedListQueue; +pub use self::queue_using_singly_linked_list::LinkedListQueue; From b3286efc6cde31c77caeb756e6dd9cbd455b8bc0 Mon Sep 17 00:00:00 2001 From: Ismael Swaleh <105565797+Ismael144@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:20:10 +0300 Subject: [PATCH 16/16] Updating queue_using_singly_linked_list.rs --- .../queue_using_singly_linked_list.rs | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/data_structures/queue_using_singly_linked_list.rs b/src/data_structures/queue_using_singly_linked_list.rs index ee8917ade16..d801737c690 100644 --- a/src/data_structures/queue_using_singly_linked_list.rs +++ b/src/data_structures/queue_using_singly_linked_list.rs @@ -1,5 +1,3 @@ -#![allow(dead_code)] - //! A queue implementation using a singly linked list //! The queue follows FIFO (First-In First-Out) principle //! The [enqueue] method's time complexity is O(1) @@ -50,7 +48,7 @@ impl Default for LinkedListQueue { } // Implement iterator for the queue -pub struct LinkedListQueueIterator<'a, T> { +pub struct LinkedListQueueIter<'a, T> { current: &'a Option>>, _marker: PhantomData<&'a T>, } @@ -69,22 +67,22 @@ where T: Debug, { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - use std::fmt::Write as _; + use std::fmt::Write as _; let mut output = String::from("LinkedListQueue ( elements: ["); - + for elem in self.iter() { let _ = write!(output, " {:?} ", elem); } - + let _ = write!(output, "], length: {} )", self.len()); - write!(f, "{}", output) + write!(f, "{}", output) } } // LinkedListQueueIterator implementation -impl<'a, T> Iterator for LinkedListQueueIterator<'a, T> { +impl<'a, T> Iterator for LinkedListQueueIter<'a, T> { type Item = &'a T; fn next(&mut self) -> Option { @@ -110,8 +108,8 @@ impl LinkedListQueue { } // Iter method, will enably us to iterate through our queue - pub fn iter(&self) -> LinkedListQueueIterator<'_, T> { - LinkedListQueueIterator { + pub fn iter(&self) -> LinkedListQueueIter<'_, T> { + LinkedListQueueIter { current: &self.tail, _marker: PhantomData, } @@ -312,6 +310,11 @@ impl LinkedListQueue { } } + /// Empty the queue + pub fn drain(&mut self) { + while self.dequeue().is_some() {} + } + /// Gets the length of the queue pub fn len(&self) -> usize { self.length @@ -326,7 +329,7 @@ impl LinkedListQueue { /// The queue implementation tests #[cfg(test)] mod tests { - use super::*; + use super::LinkedListQueue; #[test] fn test_enqueue() {