Skip to content

Commit

Permalink
PriorityQueue implemented
Browse files Browse the repository at this point in the history
  • Loading branch information
ThiagoDSMarcelino committed Dec 10, 2023
1 parent 5b29d69 commit 5c57772
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "nexum"
version = "0.1.1"
version = "0.2.0"
authors = ["Thiago dos Santos Marcelino <[email protected]>"]
edition = "2021"
description = "Library with a collection of commonly used data structures"
Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 2 additions & 0 deletions src/priority_queue/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pub use queue::PriorityQueue;
mod queue;
115 changes: 115 additions & 0 deletions src/priority_queue/queue.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
pub struct PriorityQueue<TElement, TPriority: PartialOrd> {
data: Vec<TElement>,
priorities: Vec<TPriority>,
}

impl<TElement, TPriority> Default for PriorityQueue<TElement, TPriority>
where
TPriority: PartialOrd,
{
fn default() -> Self {
Self::new()
}
}

impl<TElement, TPriority> PriorityQueue<TElement, TPriority>
where
TPriority: PartialOrd,
{
/// Creates a new [`PriorityQueue<TElement, TPriority>`].
pub fn new() -> Self {
Self {
data: Vec::new(),
priorities: Vec::new(),
}
}

/// Creates a new [`PriorityQueue<TElement, TPriority>`] 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<TElement, TPriority>`].
pub fn clear(&mut self) {
self.priorities.clear();
self.data.clear();
}

/// Returns the length of this [`PriorityQueue<TElement, TPriority>`].
pub fn len(&self) -> usize {
self.data.len()
}

/// Returns the capacity of this [`PriorityQueue<TElement, TPriority>`].
pub fn capacity(&self) -> usize {
self.data.capacity()
}

/// Returns if the [`PriorityQueue<TElement, TPriority>`] is empty.
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}

/// Removes and returns the minimal element from the [`PriorityQueue<TElement, TPriority>`] - that is, the element with the lowest priority value.
pub fn dequeue(&mut self) -> Option<TElement> {
self.priorities.pop();
self.data.pop()
}

/// Removes the minimal element and then immediately adds the specified element with associated priority to the [`PriorityQueue<TElement, TPriority>`].
pub fn dequeue_enqueue(&mut self, element: TElement, priority: TPriority) -> Option<TElement> {
let removed = self.dequeue();
self.enqueue(element, priority);

removed
}

/// Adds the specified element with associated priority to the [`PriorityQueue<TElement, TPriority>`].
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<TElement, TPriority>`], and immediately removes the minimal element, returning the result.
pub fn enqueue_dequeue(&mut self, element: TElement, priority: TPriority) -> Option<TElement> {
self.enqueue(element, priority);
self.dequeue()
}

/// Enqueues a sequence of elements pairs to the [`PriorityQueue<TElement, TPriority>`], all associated with the specified priority.
pub fn enqueue_range(&mut self, elements: Vec<TElement>, priorities: Vec<TPriority>) {
for (element, priority) in elements.into_iter().zip(priorities.into_iter()) {
self.enqueue(element, priority);
}
}

/// Ensures that the [`PriorityQueue<TElement, TPriority>`] 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<TElement, TPriority>`] without removing it.
pub fn peek(&self) -> Option<&TElement> {
self.data.last()
}

/// Sets the capacity to the actual number of items in the [`PriorityQueue<TElement, TPriority>`].
pub fn trim_to_length(&mut self) {
self.data.shrink_to_fit();
self.priorities.shrink_to_fit();
}
}
73 changes: 73 additions & 0 deletions tests/priority_queue_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#[cfg(test)]
mod tests {
use nexum::PriorityQueue;

#[test]
fn test_new() {
let queue: PriorityQueue<i32, i32> = PriorityQueue::new();
assert!(queue.is_empty());
}

#[test]
fn test_with_capacity() {
let queue: PriorityQueue<i32, i32> = 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<i32, i32> = 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);
}
}

0 comments on commit 5c57772

Please sign in to comment.