0

I'm new in rust community I'm writing a B tree implementation and have problems with refs

#[allow(dead_code)]
struct Node<'a, T: PartialOrd + Clone> {
    leaf: bool,
    count: usize,
    keys: Vec<T>,
    children: Vec<&'a mut Node<'a, T>>,
}

#[allow(dead_code)]
impl<'a, T: PartialOrd + Clone> Node<'a, T> {
    fn is_full(&self, index: usize, t: usize) -> bool {
        self.children[index].count == 2 * t - 1
    }

    fn split(&'a mut self, i: usize, t: usize) {
        let left = self.children[i];
        let ref mut right = Node::<T>::empty();

        right.leaf = left.leaf;
        right.count = t - 1;

        for j in 0..t - 1 {
            right.keys[j] = right.keys[j + t].clone()
        }

        if !left.leaf {
            for j in 0..t {
                right.children[j] = left.children[j + t];
            }
        }
    }

    fn insert_nonfull(&'a mut self, value: T, t: usize) {
        if self.leaf {
            let mut i = self.count - 1;

            while i > 0 && self.keys[i] >= value {
                self.keys[i] = self.keys[i - 1].clone();
                i -= 1;
            }

            self.keys[i] = value;
            self.count += 1;

            return;
        }

        let mut i = self.count - 1;

        while i > 0 && self.keys[i] >= value {
            i -= 1;
        }

        if self.is_full(i, t) {
            self.split(i, t);
            if value > self.keys[i]  {
                i += 1
            }
        }

        self.children[i].insert_nonfull(value, t);
    }


    fn empty() -> Self {
        return Node::<'a, T> {
            children: vec![],
            keys: vec![],
            count: 0,
            leaf: false
        }
    }

    fn leaf() -> Self {
        return Node::<'a, T> {
            children: vec![],
            keys: vec![],
            count: 0,
            leaf: true,
        };
    }
}

struct BTree<'a, T: PartialOrd + Clone> {
    root: Node<'a, T>,
    t: usize,
}

fn main() {
    let mut leaf = Node::<u32>::leaf();
}

can you help with:

  1. what type should I use for children declaration in Node? I tried Box like in Rust docs example, but it failed.
  2. can I use single lifetime annotation in impl block?
  3. how can I make private scope? I tried pub(self) or pub(super)

cargo check:

    Checking rust v0.1.0 (/Users/v8tenko/rust)
warning: unused variable: `leaf`
  --> src/main.rs:90:13
   |
90 |     let mut leaf = Node::<u32>::leaf();
   |             ^^^^ help: if this is intentional, prefix it with an underscore: `_leaf`
   |
   = note: `#[warn(unused_variables)]` on by default

error[E0507]: cannot move out of index of `Vec<Box<Node<T>>>`
  --> src/main.rs:28:37
   |
28 |                 right.children[j] = right.children[j + t]
   |                                     ^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `Box<Node<T>>`, which does not implement the `Copy` trait

warning: variable does not need to be mutable
  --> src/main.rs:90:9
   |
90 |     let mut leaf = Node::<u32>::leaf();
   |         ----^^^^
   |         |
   |         help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

For more information about this error, try `rustc --explain E0507`.
warning: `rust` (bin "rust") generated 2 warnings
error: could not compile `rust` due to previous error; 2 warnings emitted

code with Box

#[allow(dead_code)]
struct Node<T: PartialOrd + Clone> {
    leaf: bool,
    count: usize,
    keys: Vec<T>,
    children: Vec<Box<Node<T>>>,
}

#[allow(dead_code)]
impl<T: PartialOrd + Clone> Node<T> {
    fn is_full(&self, index: usize, t: usize) -> bool {
        self.children[index].count == 2 * t - 1
    }

    fn split(&mut self, i: usize, t: usize) {
        let ref mut left = self.children[i];
        let ref mut right = Node::<T>::empty();

        right.leaf = left.leaf;
        right.count = t - 1;

        for j in 0..t - 1 {
            right.keys[j] = right.keys[j + t].clone()
        }

        if !left.leaf {
            for j in 0..t {
                right.children[j] = right.children[j + t]
            }
        }
    }

    fn insert_nonfull(&mut self, value: T, t: usize) {
        if self.leaf {
            let mut i = self.count - 1;

            while i > 0 && self.keys[i] >= value {
                self.keys[i] = self.keys[i - 1].clone();
                i -= 1;
            }

            self.keys[i] = value;
            self.count += 1;

            return;
        }

        let mut i = self.count - 1;

        while i > 0 && self.keys[i] >= value {
            i -= 1;
        }

        if self.is_full(i, t) {
            self.split(i, t);
            if value > self.keys[i]  {
                i += 1
            }
        }

        self.children[i].insert_nonfull(value, t);
    }


    fn empty() -> Self {
        return Node {
            children: vec![],
            keys: vec![],
            count: 0,
            leaf: false
        }
    }

    fn leaf() -> Self {
        return Node {
            children: vec![],
            keys: vec![],
            count: 0,
            leaf: true,
        };
    }
}

struct BTree<T: PartialOrd + Clone> {
    root: Node<T>,
    t: usize,
}

fn main() {
    let mut leaf = Node::<u32>::leaf();
}
v8tenko
  • 21
  • 4

1 Answers1

1

There is a method in Vec that does exactly what you want - cut a Vec and leave part of the elements, while putting the rest of the elements in another Vec - Vec::split_off():

fn split(&mut self, i: usize, t: usize) {
    let ref mut left = self.children[i];
    let ref mut right = Node::<T>::empty();

    right.leaf = left.leaf;
    right.count = t - 1;

    right.keys = self.keys.split_off(t);

    if !left.leaf {
        right.children = self.children.split_off(t);
    }
}
Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77