From be9e685b9465b7fe2e17b4a5d5f53c3d9b8aac62 Mon Sep 17 00:00:00 2001 From: bronku Date: Sat, 6 Dec 2025 19:00:32 +0100 Subject: [PATCH] initial template --- .gitignore | 1 + Cargo.lock | 7 +++ Cargo.toml | 6 ++ src/main.rs | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 180 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0cf8360 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "btree" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4b63a77 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "btree" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..51c0f88 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,166 @@ +const MIN_DEGREE: usize = 3; // Minimum degree (minimum children per node) + +#[derive(Debug)] +pub struct BTree { + root: Option>>, +} + +#[derive(Debug)] +struct Node { + keys: Vec, + children: Vec>>, + is_leaf: bool, +} + +impl Node { + fn new(is_leaf: bool) -> Self { + Node { + keys: Vec::new(), + children: Vec::new(), + is_leaf, + } + } + + fn is_full(&self) -> bool { + self.keys.len() >= 2 * MIN_DEGREE - 1 + } + + fn search(&self, key: &K) -> bool { + let mut i = 0; + while i < self.keys.len() && key > &self.keys[i] { + i += 1; + } + + if i < self.keys.len() && key == &self.keys[i] { + return true; + } + + if self.is_leaf { + return false; + } + + self.children[i].search(key) + } + + fn insert_non_full(&mut self, key: K) { + let mut i = self.keys.len(); + + if self.is_leaf { + self.keys.push(key); + i = self.keys.len() - 1; + while i > 0 && self.keys[i] < self.keys[i - 1] { + self.keys.swap(i, i - 1); + i -= 1; + } + } else { + while i > 0 && key < self.keys[i - 1] { + i -= 1; + } + + if self.children[i].is_full() { + self.split_child(i); + if key > self.keys[i] { + i += 1; + } + } + self.children[i].insert_non_full(key); + } + } + + fn split_child(&mut self, i: usize) { + let t = MIN_DEGREE; + let full_child = &mut self.children[i]; + let mut new_child = Box::new(Node::new(full_child.is_leaf)); + + // Move the second half of keys to new child + new_child.keys = full_child.keys.split_off(t); + let median = full_child.keys.pop().unwrap(); + + // Move the second half of children if not a leaf + if !full_child.is_leaf { + new_child.children = full_child.children.split_off(t); + } + + // Insert median key and new child into parent + self.keys.insert(i, median); + self.children.insert(i + 1, new_child); + } +} + +impl BTree { + pub fn new() -> Self { + BTree { root: None } + } + + pub fn insert(&mut self, key: K) { + match &mut self.root { + None => { + let mut root = Box::new(Node::new(true)); + root.keys.push(key); + self.root = Some(root); + } + Some(root) => { + if root.is_full() { + let mut new_root = Box::new(Node::new(false)); + let old_root = self.root.take().unwrap(); + new_root.children.push(old_root); + new_root.split_child(0); + new_root.insert_non_full(key); + self.root = Some(new_root); + } else { + root.insert_non_full(key); + } + } + } + } + + pub fn search(&self, key: &K) -> bool { + match &self.root { + None => false, + Some(root) => root.search(key), + } + } + + pub fn print_tree(&self) { + if let Some(root) = &self.root { + Self::print_node(root, 0); + } else { + println!("Empty tree"); + } + } + + fn print_node(node: &Node, level: usize) + where + K: std::fmt::Debug, + { + print!("{}", " ".repeat(level)); + println!("Keys: {:?}", node.keys); + + if !node.is_leaf { + for child in &node.children { + Self::print_node(child, level + 1); + } + } + } +} + +fn main() { + let mut btree = BTree::new(); + + // Insert some values + let values = vec![10, 20, 5, 6, 12, 30, 7, 17, 3, 16, 21, 22, 23, 24]; + + println!("Inserting values: {:?}", values); + for val in values { + btree.insert(val); + } + + println!("\nB-Tree structure:"); + btree.print_tree(); + + // Search for some values + println!("\nSearch results:"); + println!("Search for 6: {}", btree.search(&6)); + println!("Search for 15: {}", btree.search(&15)); + println!("Search for 21: {}", btree.search(&21)); +}