From 5c577729f0736ec223e7cd9d5f04c883a3370732 Mon Sep 17 00:00:00 2001 From: ThiagoDSMarcelino Date: Sun, 10 Dec 2023 17:06:56 -0300 Subject: [PATCH] PriorityQueue implemented --- Cargo.toml | 2 +- src/lib.rs | 2 + src/priority_queue/mod.rs | 2 + src/priority_queue/queue.rs | 115 +++++++++++++++++++++++++++++++++++ tests/priority_queue_test.rs | 73 ++++++++++++++++++++++ 5 files changed, 193 insertions(+), 1 deletion(-) create mode 100644 src/priority_queue/mod.rs create mode 100644 src/priority_queue/queue.rs create mode 100644 tests/priority_queue_test.rs diff --git a/Cargo.toml b/Cargo.toml index 0fe048e..18811dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "nexum" -version = "0.1.1" +version = "0.2.0" authors = ["Thiago dos Santos Marcelino "] edition = "2021" description = "Library with a collection of commonly used data structures" diff --git a/src/lib.rs b/src/lib.rs index 7e50e70..94bdd8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,9 @@ pub use auto_expand_vector::AutoExpandVector; pub use hash_table::HashTable; pub use linked_list::LinkedList; +pub use priority_queue::PriorityQueue; mod auto_expand_vector; mod hash_table; mod linked_list; +mod priority_queue; diff --git a/src/priority_queue/mod.rs b/src/priority_queue/mod.rs new file mode 100644 index 0000000..f8477d6 --- /dev/null +++ b/src/priority_queue/mod.rs @@ -0,0 +1,2 @@ +pub use queue::PriorityQueue; +mod queue; \ No newline at end of file diff --git a/src/priority_queue/queue.rs b/src/priority_queue/queue.rs new file mode 100644 index 0000000..a705e30 --- /dev/null +++ b/src/priority_queue/queue.rs @@ -0,0 +1,115 @@ +pub struct PriorityQueue { + data: Vec, + priorities: Vec, +} + +impl Default for PriorityQueue +where + TPriority: PartialOrd, +{ + fn default() -> Self { + Self::new() + } +} + +impl PriorityQueue +where + TPriority: PartialOrd, +{ + /// Creates a new [`PriorityQueue`]. + pub fn new() -> Self { + Self { + data: Vec::new(), + priorities: Vec::new(), + } + } + + /// Creates a new [`PriorityQueue`] with the specified capacity. + pub fn with_capacity(capacity: usize) -> Self { + Self { + data: Vec::with_capacity(capacity), + priorities: Vec::with_capacity(capacity), + } + } + + /// Removes all items from the [`PriorityQueue`]. + pub fn clear(&mut self) { + self.priorities.clear(); + self.data.clear(); + } + + /// Returns the length of this [`PriorityQueue`]. + pub fn len(&self) -> usize { + self.data.len() + } + + /// Returns the capacity of this [`PriorityQueue`]. + pub fn capacity(&self) -> usize { + self.data.capacity() + } + + /// Returns if the [`PriorityQueue`] is empty. + pub fn is_empty(&self) -> bool { + self.data.is_empty() + } + + /// Removes and returns the minimal element from the [`PriorityQueue`] - that is, the element with the lowest priority value. + pub fn dequeue(&mut self) -> Option { + self.priorities.pop(); + self.data.pop() + } + + /// Removes the minimal element and then immediately adds the specified element with associated priority to the [`PriorityQueue`]. + pub fn dequeue_enqueue(&mut self, element: TElement, priority: TPriority) -> Option { + let removed = self.dequeue(); + self.enqueue(element, priority); + + removed + } + + /// Adds the specified element with associated priority to the [`PriorityQueue`]. + pub fn enqueue(&mut self, element: TElement, priority: TPriority) { + let mut index = 0; + + while let Some(data_priority) = self.priorities.get(index) { + if &priority > data_priority { + break; + } + + index += 1; + } + + self.data.insert(index, element); + self.priorities.insert(index, priority); + } + + /// Adds the specified element with associated priority to the [`PriorityQueue`], and immediately removes the minimal element, returning the result. + pub fn enqueue_dequeue(&mut self, element: TElement, priority: TPriority) -> Option { + self.enqueue(element, priority); + self.dequeue() + } + + /// Enqueues a sequence of elements pairs to the [`PriorityQueue`], all associated with the specified priority. + pub fn enqueue_range(&mut self, elements: Vec, priorities: Vec) { + for (element, priority) in elements.into_iter().zip(priorities.into_iter()) { + self.enqueue(element, priority); + } + } + + /// Ensures that the [`PriorityQueue`] can hold up to `capacity` items without further expansion of its backing storage. + pub fn ensure_capacity(&mut self, capacity: usize) { + self.data.reserve(capacity); + self.priorities.reserve(capacity); + } + + /// Returns the minimal element from the [`PriorityQueue`] without removing it. + pub fn peek(&self) -> Option<&TElement> { + self.data.last() + } + + /// Sets the capacity to the actual number of items in the [`PriorityQueue`]. + pub fn trim_to_length(&mut self) { + self.data.shrink_to_fit(); + self.priorities.shrink_to_fit(); + } +} diff --git a/tests/priority_queue_test.rs b/tests/priority_queue_test.rs new file mode 100644 index 0000000..b280379 --- /dev/null +++ b/tests/priority_queue_test.rs @@ -0,0 +1,73 @@ +#[cfg(test)] +mod tests { + use nexum::PriorityQueue; + + #[test] + fn test_new() { + let queue: PriorityQueue = PriorityQueue::new(); + assert!(queue.is_empty()); + } + + #[test] + fn test_with_capacity() { + let queue: PriorityQueue = PriorityQueue::with_capacity(10); + assert!(queue.is_empty()); + assert_eq!(queue.capacity(), 10); + } + + #[test] + fn test_enqueue_dequeue() { + let mut queue = PriorityQueue::new(); + queue.enqueue(1, 1); + assert_eq!(queue.dequeue(), Some(1)); + } + + #[test] + fn test_enqueue_dequeue_with_priority() { + let mut queue = PriorityQueue::new(); + queue.enqueue(1, 2); + queue.enqueue(2, 1); + assert_eq!(queue.dequeue(), Some(2)); + assert_eq!(queue.dequeue(), Some(1)); + } + + #[test] + fn test_peek() { + let mut queue = PriorityQueue::new(); + assert_eq!(queue.peek(), None); + queue.enqueue(1, 1); + assert_eq!(queue.peek(), Some(&1)); + } + + #[test] + fn test_clear() { + let mut queue = PriorityQueue::new(); + queue.enqueue(1, 1); + queue.clear(); + assert!(queue.is_empty()); + } + + #[test] + fn test_enqueue_range() { + let mut queue = PriorityQueue::new(); + queue.enqueue_range(vec![1, 2, 3], vec![5, 1, 0]); + assert_eq!(queue.dequeue(), Some(3)); + assert_eq!(queue.dequeue(), Some(2)); + assert_eq!(queue.dequeue(), Some(1)); + } + + #[test] + fn test_ensure_capacity() { + let mut queue: PriorityQueue = PriorityQueue::new(); + queue.ensure_capacity(10); + assert!(queue.capacity() >= 10); + } + + #[test] + fn test_trim_to_length() { + let mut queue = PriorityQueue::with_capacity(10); + queue.enqueue_range(vec![1, 2, 3], vec![1, 2, 3]); + queue.trim_to_length(); + assert!(queue.capacity() <= 4); + } +}