Compare commits
2 commits
325c491691
...
d63222a6ef
Author | SHA1 | Date | |
---|---|---|---|
d63222a6ef | |||
9f09799413 |
2 changed files with 139 additions and 18 deletions
|
@ -1,9 +1,20 @@
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
use crate::vec::Vec;
|
use crate::vec::Vec;
|
||||||
|
|
||||||
|
pub const DEFAULT_DEGREE: usize = 1;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct BTree<T> {
|
pub struct BTree<T: Ord + Clone> {
|
||||||
root: Node<T>,
|
root: Node<T>,
|
||||||
|
properties: BTreeProperties,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Copy)]
|
||||||
|
pub struct BTreeProperties {
|
||||||
degree: usize,
|
degree: usize,
|
||||||
|
max_keys: usize,
|
||||||
|
mid_key_index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -12,6 +23,63 @@ struct Node<T> {
|
||||||
children: Vec<Node<T>>,
|
children: Vec<Node<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BTreeProperties {
|
||||||
|
fn new(degree: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
degree,
|
||||||
|
max_keys: degree - 1,
|
||||||
|
mid_key_index: (degree - 1) / 2,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn split_child<T: Ord + Clone>(&self, parent: &mut Node<T>, child_index: usize) {
|
||||||
|
let child = &mut parent.children[child_index];
|
||||||
|
let middle_key: T = child.keys[self.mid_key_index].clone();
|
||||||
|
let right_keys = match child.keys.split_off(self.mid_key_index).split_first() {
|
||||||
|
Some((_first, _others)) => {
|
||||||
|
// We don't need _first, as it will move to parent node.
|
||||||
|
_others.into()
|
||||||
|
}
|
||||||
|
None => Vec::<T>::with_capacity(self.max_keys),
|
||||||
|
};
|
||||||
|
let right_children = if !child.is_leaf() {
|
||||||
|
Some(child.children.split_off(self.mid_key_index + 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let new_child_node: Node<T> = Node::new(self.degree, Some(right_keys), right_children);
|
||||||
|
|
||||||
|
parent.keys.insert(child_index, middle_key);
|
||||||
|
parent.children.insert(child_index + 1, new_child_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_maxed_out<T: Ord>(&self, node: &Node<T>) -> bool {
|
||||||
|
node.keys.len() == self.max_keys
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_non_full<T: Ord + Clone>(&mut self, node: &mut Node<T>, key: T) {
|
||||||
|
let mut index: isize = isize::try_from(node.keys.len()).ok().unwrap() - 1;
|
||||||
|
while index >= 0 && node.keys[index as usize] >= key {
|
||||||
|
index -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut u_index: usize = usize::try_from(index + 1).ok().unwrap();
|
||||||
|
if node.is_leaf() {
|
||||||
|
// Just insert it, as we know this method will be called only when node is not full
|
||||||
|
node.keys.insert(u_index, key);
|
||||||
|
} else {
|
||||||
|
if self.is_maxed_out(&node.children[u_index]) {
|
||||||
|
self.split_child(node, u_index);
|
||||||
|
if node.keys[u_index] < key {
|
||||||
|
u_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.insert_non_full(&mut node.children[u_index], key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Node<T>
|
impl<T> Node<T>
|
||||||
where
|
where
|
||||||
T: Ord,
|
T: Ord,
|
||||||
|
@ -34,47 +102,63 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Ord> BTree<T> {
|
impl<T: Ord + Clone> BTree<T> {
|
||||||
pub fn new(branch_factor: usize) -> Self {
|
pub fn new(branch_factor: usize) -> Self {
|
||||||
let degree = 2 * branch_factor;
|
let degree = 2 * branch_factor;
|
||||||
Self {
|
Self {
|
||||||
root: Node::new(degree, None, None),
|
root: Node::new(degree, None, None),
|
||||||
degree,
|
properties: BTreeProperties::new(degree),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
self.root = Node::new(self.degree, None, None);
|
self.root = Node::new(self.properties.degree, None, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rebalance() {
|
pub fn insert(&mut self, key: T) {
|
||||||
todo!()
|
if self.properties.is_maxed_out(&self.root) {
|
||||||
|
// Create an empty root and split the old root...
|
||||||
|
let mut new_root = Node::new(self.properties.degree, None, None);
|
||||||
|
mem::swap(&mut new_root, &mut self.root);
|
||||||
|
self.root.children.insert(0, new_root);
|
||||||
|
self.properties.split_child(&mut self.root, 0);
|
||||||
|
}
|
||||||
|
self.properties.insert_non_full(&mut self.root, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, value: T) -> Option<T> {
|
#[must_use]
|
||||||
todo!()
|
pub fn has(&self, key: T) -> bool {
|
||||||
}
|
let mut current_node = &self.root;
|
||||||
|
loop {
|
||||||
pub fn has(&self, value: T) -> bool {
|
match current_node.keys.binary_search(&key) {
|
||||||
todo!()
|
Ok(_) => return true,
|
||||||
|
Err(idx) => {
|
||||||
|
if current_node.is_leaf() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
current_node = ¤t_node.children[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create() {
|
fn test_create() {
|
||||||
let _tree = BTree::<u32>::new();
|
let _tree = BTree::<u32>::new(DEFAULT_DEGREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insert() {
|
fn test_insert() {
|
||||||
let mut tree = BTree::<u32>::new();
|
let mut tree = BTree::<u32>::new(DEFAULT_DEGREE);
|
||||||
let data = &[19, 125, 25, 16, 2, 73, 384, 435, 12924, 42, 125251, 2548];
|
let data = &[19, 125, 25, 16, 2, 73, 384, 435, 12924, 42, 125251, 2548];
|
||||||
|
|
||||||
for d in data {
|
for d in data {
|
||||||
assert!(tree.insert(*d).is_none())
|
tree.insert(*d)
|
||||||
}
|
}
|
||||||
|
|
||||||
for d in data {
|
for d in data {
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
//! https://doc.rust-lang.org/nomicon/vec/vec.html
|
//! https://doc.rust-lang.org/nomicon/vec/vec.html
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
marker::PhantomData,
|
|
||||||
mem,
|
mem,
|
||||||
ops::{Deref, DerefMut, Index, IndexMut},
|
ops::{Deref, DerefMut, Index, IndexMut},
|
||||||
ptr,
|
ptr,
|
||||||
|
@ -15,7 +14,6 @@ use crate::raw_vec::RawVec;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Vec<T> {
|
pub struct Vec<T> {
|
||||||
used: usize,
|
used: usize,
|
||||||
marker: PhantomData<T>,
|
|
||||||
buf: RawVec<T>,
|
buf: RawVec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +30,6 @@ impl<T> Vec<T> {
|
||||||
}
|
}
|
||||||
Vec {
|
Vec {
|
||||||
used: 0,
|
used: 0,
|
||||||
marker: PhantomData,
|
|
||||||
buf: RawVec::new(),
|
buf: RawVec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,6 +44,14 @@ impl<T> Vec<T> {
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_slice(data: &[T]) -> Self {
|
||||||
|
let mut v = Vec::<T>::with_capacity(data.len());
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(data.as_ptr(), v.as_mut_ptr(), data.len());
|
||||||
|
}
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
pub fn pop(&mut self) -> Option<T> {
|
pub fn pop(&mut self) -> Option<T> {
|
||||||
if self.used == 0 {
|
if self.used == 0 {
|
||||||
None
|
None
|
||||||
|
@ -121,6 +126,32 @@ impl<T> Vec<T> {
|
||||||
pub fn reserve(&mut self, added_capacity: usize) {
|
pub fn reserve(&mut self, added_capacity: usize) {
|
||||||
self.buf.grow_by(added_capacity);
|
self.buf.grow_by(added_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn split_off(&mut self, at: usize) -> Self {
|
||||||
|
let other_len = self.used - at;
|
||||||
|
let mut other = Self::with_capacity(other_len);
|
||||||
|
unsafe {
|
||||||
|
self.set_len(at);
|
||||||
|
other.set_len(other_len);
|
||||||
|
ptr::copy_nonoverlapping(self.as_ptr().add(at), other.as_mut_ptr(), other.len());
|
||||||
|
}
|
||||||
|
other
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn set_len(&mut self, new_length: usize) {
|
||||||
|
self.used = new_length
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn as_ptr(&self) -> *const T {
|
||||||
|
self.buf.ptr.as_ptr()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn as_mut_ptr(&mut self) -> *mut T {
|
||||||
|
self.buf.ptr.as_ptr()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Index<usize> for Vec<T> {
|
impl<T> Index<usize> for Vec<T> {
|
||||||
|
@ -158,6 +189,12 @@ impl<T> Drop for Vec<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> From<&[T]> for Vec<T> {
|
||||||
|
fn from(value: &[T]) -> Self {
|
||||||
|
Self::from_slice(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl<T: Send> Send for Vec<T> {}
|
unsafe impl<T: Send> Send for Vec<T> {}
|
||||||
unsafe impl<T: Sync> Sync for Vec<T> {}
|
unsafe impl<T: Sync> Sync for Vec<T> {}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue