refactored

This commit is contained in:
specCon18 2024-05-24 05:07:46 -04:00
parent 64340ce50a
commit 3790330936
12 changed files with 9 additions and 9 deletions

View file

@ -0,0 +1,116 @@
/// A min-heap data structure for managing elements based on their order.
///
/// This struct implements a min-heap, where the smallest element is always at the top.
/// It is generic over type `T`, which must implement the `PartialOrd` trait.
pub struct MinHeap<T> {
data: Vec<T>,
}
impl<T: PartialOrd> MinHeap<T> {
/// Creates a new, empty `MinHeap`.
///
/// # Examples
///
/// ```
/// use min_heap::MinHeap;
///
/// let mut heap: MinHeap<i32> = MinHeap::new();
/// ```
pub fn new() -> Self {
MinHeap { data: Vec::new() }
}
/// Pushes an element onto the heap.
///
/// # Arguments
///
/// * `element` - The element to be pushed onto the heap.
///
/// # Examples
///
/// ```
/// use min_heap::MinHeap;
///
/// let mut heap: MinHeap<i32> = MinHeap::new();
/// heap.push(5);
/// heap.push(3);
/// ```
pub fn push(&mut self, element: T) {
self.data.push(element);
self.heapify_up(self.data.len() - 1);
}
/// Pops the smallest element from the heap.
///
/// This removes and returns the smallest element from the heap.
///
/// # Returns
///
/// The smallest element, if the heap is not empty.
///
/// # Examples
///
/// ```
/// use min_heap::MinHeap;
///
/// let mut heap: MinHeap<i32> = MinHeap::new();
/// heap.push(5);
/// heap.push(3);
/// assert_eq!(heap.pop(), Some(3));
/// ```
pub fn pop(&mut self) -> Option<T> {
if self.data.is_empty() {
return None;
}
let last_index = self.data.len() - 1;
self.data.swap(0, last_index);
let result = self.data.pop();
self.heapify_down(0);
result
}
/// Maintains the heap property by moving an element up.
///
/// # Arguments
///
/// * `index` - The index of the element to be moved up.
fn heapify_up(&mut self, mut index: usize) {
while index != 0 {
let parent_index = (index - 1) / 2;
if self.data[index] < self.data[parent_index] {
self.data.swap(parent_index, index);
}
index = parent_index;
}
}
/// Maintains the heap property by moving an element down.
///
/// # Arguments
///
/// * `index` - The index of the element to be moved down.
fn heapify_down(&mut self, mut index: usize) {
let length = self.data.len();
loop {
let left_child = 2 * index + 1;
let right_child = 2 * index + 2;
let mut smallest = index;
if left_child < length && self.data[left_child] < self.data[smallest] {
smallest = left_child;
}
if right_child < length && self.data[right_child] < self.data[smallest] {
smallest = right_child;
}
if smallest != index {
self.data.swap(index, smallest);
index = smallest;
} else {
break;
}
}
}
}

View file

@ -0,0 +1,5 @@
pub mod queue;
pub mod stack;
pub mod min_heap;
pub mod weighted_adj_list;
pub mod ring_buffer;

View file

@ -0,0 +1,24 @@
pub struct Queue<T> {
queue: Vec<T>,
}
impl<T> Queue<T> {
pub fn new() -> Self {
Queue { queue: Vec::new() }
}
pub fn length(&self) -> usize {
self.queue.len()
}
pub fn enqueue(&mut self, item: T) {
self.queue.push(item)
}
pub fn dequeue(&mut self) -> T {
self.queue.remove(0)
}
pub fn is_empty(&self) -> bool {
self.queue.is_empty()
}
pub fn peek(&self) -> Option<&T> {
self.queue.first()
}
}

View file

@ -0,0 +1,111 @@
#[cfg(test)]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_push_and_pop() {
let mut buffer: RingBuffer<i32> = RingBuffer::new(5);
buffer.push(1);
buffer.push(2);
buffer.push(3);
assert_eq!(buffer.pop(), Some(1));
assert_eq!(buffer.pop(), Some(2));
assert_eq!(buffer.pop(), Some(3));
}
#[test]
fn test_peek() {
let mut buffer: RingBuffer<i32> = RingBuffer::new(3);
buffer.push(10);
buffer.push(20);
assert_eq!(buffer.peek(), Some(&10));
buffer.pop();
assert_eq!(buffer.peek(), Some(&20));
}
#[test]
fn test_pop_from_empty_buffer() {
let mut buffer: RingBuffer<i32> = RingBuffer::new(2);
assert_eq!(buffer.pop(), None);
}
#[test]
fn test_buffer_length_and_capacity() {
let mut buffer: RingBuffer<i32> = RingBuffer::new(4);
buffer.push(1);
buffer.push(2);
assert_eq!(buffer.len(), 2);
assert_eq!(buffer.capacity(), 4);
}
#[test]
fn test_is_empty() {
let mut buffer: RingBuffer<i32> = RingBuffer::new(3);
assert!(buffer.is_empty());
buffer.push(100);
assert!(!buffer.is_empty());
buffer.pop();
assert!(buffer.is_empty());
}
}
pub struct RingBuffer<T> {
buffer: Vec<Option<T>>,
capacity: usize,
read_pos: usize,
write_pos: usize,
}
impl<T> RingBuffer<T> {
pub fn new(capacity: usize) -> Self {
let mut buffer = Vec::with_capacity(capacity);
for _ in 0..capacity {
buffer.push(None);
}
RingBuffer {
buffer,
capacity,
read_pos: 0,
write_pos: 0,
}
}
pub fn push(&mut self, item: T) {
self.buffer[self.write_pos] = Some(item);
if self.len() == self.capacity {
self.read_pos = (self.read_pos + 1) % self.capacity; // Move read position if the buffer is full
}
self.write_pos = (self.write_pos + 1) % self.capacity;
}
pub fn pop(&mut self) -> Option<T> {
if self.read_pos == self.write_pos {
return None; // Buffer is empty
}
let item = self.buffer[self.read_pos].take();
self.read_pos = (self.read_pos + 1) % self.capacity;
item
}
pub fn peek(&self) -> Option<&T> {
self.buffer[self.read_pos].as_ref().map(|item| item)
}
pub fn is_empty(&self) -> bool {
self.read_pos == self.write_pos
}
pub fn len(&self) -> usize {
if self.read_pos <= self.write_pos {
self.write_pos - self.read_pos
} else {
self.capacity - self.read_pos + self.write_pos
}
}
pub fn capacity(&self) -> usize {
self.capacity
}
}

View file

@ -0,0 +1,24 @@
pub struct Stack<T> {
stack: Vec<T>,
}
impl<T> Stack<T> {
pub fn new() -> Self {
Stack { stack: Vec::new() }
}
pub fn length(&self) -> usize {
self.stack.len()
}
pub fn pop(&mut self) -> Option<T> {
self.stack.pop()
}
pub fn push(&mut self, item: T) {
self.stack.push(item)
}
pub fn is_empty(&self) -> bool {
self.stack.is_empty()
}
pub fn peek(&self) -> Option<&T> {
self.stack.last()
}
}

View file

@ -0,0 +1,58 @@
use std::collections::HashMap;
pub struct WeightedAdjacencyList<T, W> {
vertices: HashMap<T, HashMap<T, W>>,
}
impl<T, W> Clone for WeightedAdjacencyList<T, W>
where
T: Clone,
W: Clone,
{
fn clone(&self) -> Self {
WeightedAdjacencyList {
vertices: self.vertices.clone(),
}
}
}
impl<T, W> WeightedAdjacencyList<T, W>
where
T: std::hash::Hash + Eq + Clone,
{
// Constructor to create a new weighted adjacency list
pub fn new() -> Self {
WeightedAdjacencyList {
vertices: HashMap::new(),
}
}
// Method to add a vertex to the adjacency list
pub fn add_vertex(&mut self, vertex: T) {
self.vertices.entry(vertex).or_insert(HashMap::new());
}
// Method to add an edge with weight between two vertices
pub fn add_edge(&mut self, from: T, to: T, weight: W) {
// Ensure both vertices exist in the adjacency list
self.add_vertex(from.clone());
self.add_vertex(to.clone());
// Add the edge from 'from' to 'to' with weight
self.vertices.get_mut(&from).unwrap().insert(to, weight);
}
// Method to get the weight of an edge between two vertices
pub fn get_weight(&self, from: &T, to: &T) -> Option<&W> {
self.vertices.get(from)?.get(to)
}
// Method to get the neighbors of a vertex
pub fn get_neighbors(&self, vertex: &T) -> Option<&HashMap<T, W>> {
self.vertices.get(vertex)
}
// Method to get the number of vertices in the adjacency list
pub fn len(&self) -> usize {
self.vertices.len()
}
}