got binary tree insert working need to isolate traversal and setup delete

This commit is contained in:
specCon18 2024-05-19 19:54:02 -04:00
parent 74d3013a2e
commit 6067c1bebe
8 changed files with 424 additions and 225 deletions

194
src/binary_tree.rs Normal file
View file

@ -0,0 +1,194 @@
use std::collections::VecDeque;
#[cfg(test)]
mod tests {
use super::BinaryTree;
#[test]
fn create_new_tree() {
let tree = BinaryTree::new(1);
assert_eq!(tree.value, 1);
}
#[test]
fn insert_left() {
let tree = BinaryTree::new(1).left(BinaryTree::new(2));
if let Some(node) = tree.left {
assert_eq!(node.value, 2);
}
assert_eq!(tree.right, None);
}
#[test]
fn insert_right() {
let tree = BinaryTree::new(1).right(BinaryTree::new(2));
if let Some(node) = tree.right {
assert_eq!(node.value, 2);
}
assert_eq!(tree.left, None);
}
#[test]
fn insert() {
let mut tree = BinaryTree::new(1);
tree.insert(2);
tree.insert(3);
tree.insert(4);
tree.insert(5);
assert_eq!(
tree,
BinaryTree::new(1)
.left(BinaryTree::new(2).left(BinaryTree::new(4)).right(BinaryTree::new(5)))
.right(BinaryTree::new(3))
);
tree.insert(6);
assert_eq!(
tree,
BinaryTree::new(1)
.left(BinaryTree::new(2).left(BinaryTree::new(4)).right(BinaryTree::new(5)))
.right(BinaryTree::new(3).left(BinaryTree::new(6)))
)
}
#[test]
fn create_new_tree_with_from() {
// `BinaryTree::from` takes in a reference of an array because borrowing is sufficient
let tree = BinaryTree::from(&[1, 2, 3, 4, 5, 6]);
assert_eq!(
tree,
BinaryTree::new(1)
.left(BinaryTree::new(2).left(BinaryTree::new(4)).right(BinaryTree::new(5)))
.right(BinaryTree::new(3).left(BinaryTree::new(6)))
)
}
}
/// A binary tree data structure.
#[derive(PartialEq, Debug)]
pub struct BinaryTree<T> {
/// The value stored in the node.
pub value: T,
/// The left child of the node.
pub left: Option<Box<BinaryTree<T>>>,
/// The right child of the node.
pub right: Option<Box<BinaryTree<T>>>,
}
impl<T> BinaryTree<T>
where
T: Copy + PartialEq,
{
/// Creates a new binary tree node with the given value.
///
/// # Arguments
///
/// * `value` - The value to store in the node.
///
/// # Returns
///
/// A new binary tree node with the given value and no children.
pub fn new(value: T) -> Self {
BinaryTree {
value,
left: None,
right: None,
}
}
/// Inserts a new value into the binary tree.
///
/// The value is inserted into the first available position in the tree,
/// following a breadth-first traversal.
///
/// # Arguments
///
/// * `new_value` - The value to insert into the tree.
pub fn insert(&mut self, new_value: T) {
let mut queue: VecDeque<&mut BinaryTree<T>> = VecDeque::new();
queue.push_front(self);
loop {
let BinaryTree {
ref mut left,
ref mut right,
..
} = queue.pop_back().unwrap();
match left {
Some(node) => {
queue.push_front(node);
}
None => {
*left = Some(Box::new(BinaryTree::new(new_value)));
return;
}
}
match right {
Some(node) => {
queue.push_front(node);
}
None => {
*right = Some(Box::new(BinaryTree::new(new_value)));
return;
}
}
}
}
/// Creates a binary tree from a slice of values.
///
/// The first value in the slice is used as the root of the tree,
/// and the remaining values are inserted into the tree in breadth-first order.
///
/// # Arguments
///
/// * `new_values` - A slice containing the values to insert into the tree.
///
/// # Returns
///
/// A binary tree containing the values from the input slice.
pub fn from(new_values: &[T]) -> Self {
let (first, rest) = new_values.split_first().unwrap();
let mut root: BinaryTree<T> = BinaryTree::new(*first);
for value in rest {
root.insert(*value)
}
root
}
/// Adds a left child to the current node.
///
/// # Arguments
///
/// * `node` - The binary tree node to add as the left child.
///
/// # Returns
///
/// A new binary tree node with the specified left child.
fn left(mut self, node: BinaryTree<T>) -> Self {
self.left = Some(Box::new(node));
self
}
/// Adds a right child to the current node.
///
/// # Arguments
///
/// * `node` - The binary tree node to add as the right child.
///
/// # Returns
///
/// A new binary tree node with the specified right child.
fn right(mut self, node: BinaryTree<T>) -> Self {
self.right = Some(Box::new(node));
self
}
}

View file

@ -1,224 +1 @@
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()
}
}
/// 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;
}
}
}
}
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()
}
}
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

@ -1,7 +1,8 @@
use crate::data_structures::{WeightedAdjacencyList,MinHeap}; use crate::weighted_adj_list::{WeightedAdjacencyList};
use crate::min_heap::MinHeap;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::data_structures::WeightedAdjacencyList; use crate::weighted_adj_list::WeightedAdjacencyList;
use super::dijkstras_shortest_path; use super::dijkstras_shortest_path;
#[test] #[test]
fn dijkstras_shortest_path_primeagen_class_test(){ fn dijkstras_shortest_path_primeagen_class_test(){

View file

@ -3,6 +3,11 @@ mod binary_search;
mod bubble_sort; mod bubble_sort;
mod quick_sort; mod quick_sort;
mod dijkstras; mod dijkstras;
mod queue;
mod stack;
mod binary_tree;
mod min_heap;
mod weighted_adj_list;
mod data_structures; mod data_structures;
fn linear_search_demo(){ fn linear_search_demo(){
println!("-------------------"); println!("-------------------");

116
src/min_heap.rs Normal file
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;
}
}
}
}

24
src/queue.rs Normal file
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()
}
}

24
src/stack.rs Normal file
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()
}
}

58
src/weighted_adj_list.rs Normal file
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()
}
}