platform-trees 0.3.4

Trees methods for linksplatform
Documentation
use crate::RecursiveSizeBalancedTree;
use platform_num::LinkReference;

/// Extends [`RecursiveSizeBalancedTree`] with iterative `attach` and
/// `detach` operations.
///
/// The iterative approach avoids stack overflow on deep trees by using
/// a loop with pointer-chasing instead of recursion.
///
/// # Usage
///
/// Implement [`RecursiveSizeBalancedTree`] for your storage type, then
/// add an empty `impl IterativeSizeBalancedTree<T> for MyStorage {}`.
///
/// # Safety
///
/// All methods are `unsafe` — the caller must ensure that `root` points
/// to a valid, writable location and that `node` indices are valid.
pub trait IterativeSizeBalancedTree<T: LinkReference>: RecursiveSizeBalancedTree<T> {
    /// Inserts `node` into the tree rooted at `*root`.
    ///
    /// If `*root` is zero (empty tree), `node` becomes the root with
    /// size 1. Otherwise the tree is rebalanced after insertion.
    unsafe fn attach(&mut self, root: *mut T, node: T) {
        unsafe {
            if *root == T::from_byte(0) {
                self.set_size(node, T::from_byte(1));
                *root = node;
                return;
            }
            self.attach_core(root, node);
        }
    }
    /// Removes `node` from the tree rooted at `*root`.
    ///
    /// The tree is rebalanced after removal. After detach, `node`'s
    /// left, right, and size fields are cleared to zero.
    unsafe fn detach(&mut self, root: *mut T, node: T) {
        unsafe {
            self.detach_core(root, node);
        }
    }

    unsafe fn attach_core(&mut self, mut root: *mut T, node: T) {
        unsafe {
            loop {
                let left = self.get_mut_left_reference(*root);
                let left_size = self.get_size_or_zero(*left);
                let right = self.get_mut_right_reference(*root);
                let right_size = self.get_size_or_zero(*right);
                if self.first_is_to_the_left_of_second(node, *root) {
                    if *left == T::from_byte(0) {
                        self.inc_size(*root);
                        self.set_size(node, T::from_byte(1));
                        *left = node;
                        return;
                    }
                    if self.first_is_to_the_left_of_second(node, *left) {
                        if (left_size + T::from_byte(1)) > right_size {
                            self.right_rotate(root);
                        } else {
                            self.inc_size(*root);
                            root = left;
                        }
                    } else {
                        let left_right_size = self.get_size_or_zero(self.get_right(*left));
                        if (left_right_size + T::from_byte(1)) > right_size {
                            if left_right_size == T::from_byte(0) && right_size == T::from_byte(0) {
                                self.set_left(node, *left);
                                self.set_right(node, *root);
                                self.set_size(node, left_size + T::from_byte(1) + T::from_byte(1));
                                self.set_left(*root, T::from_byte(0));
                                self.set_size(*root, T::from_byte(1));
                                *root = node;
                                return;
                            }
                            self.left_rotate(left);
                            self.right_rotate(root);
                        } else {
                            self.inc_size(*root);
                            root = left;
                        }
                    }
                } else {
                    if *right == T::from_byte(0) {
                        self.inc_size(*root);
                        self.set_size(node, T::from_byte(1));
                        *right = node;
                        return;
                    }
                    if self.first_is_to_the_right_of_second(node, *right) {
                        if (right_size + T::from_byte(1)) > left_size {
                            self.left_rotate(root);
                        } else {
                            self.inc_size(*root);
                            root = right;
                        }
                    } else {
                        let right_left_size = self.get_size_or_zero(self.get_left(*right));
                        if (right_left_size + T::from_byte(1)) > left_size {
                            if right_left_size == T::from_byte(0) && left_size == T::from_byte(0) {
                                self.set_left(node, *root);
                                self.set_right(node, *right);
                                self.set_size(node, right_size + T::from_byte(1) + T::from_byte(1));
                                self.set_right(*root, T::from_byte(0));
                                self.set_size(*root, T::from_byte(1));
                                *root = node;
                                return;
                            }
                            self.right_rotate(right);
                            self.left_rotate(root);
                        } else {
                            self.inc_size(*root);
                            root = right;
                        }
                    }
                }
            }
        }
    }

    unsafe fn detach_core(&mut self, mut root: *mut T, node: T) {
        unsafe {
            loop {
                let left = self.get_mut_left_reference(*root);
                let left_size = self.get_size_or_zero(*left);
                let right = self.get_mut_right_reference(*root);
                let right_size = self.get_size_or_zero(*right);
                if self.first_is_to_the_left_of_second(node, *root) {
                    let decremented_left_size = left_size - T::from_byte(1);
                    if self.get_size_or_zero(self.get_right_or_default(*right))
                        > decremented_left_size
                    {
                        self.left_rotate(root);
                    } else if self.get_size_or_zero(self.get_left_or_default(*right))
                        > decremented_left_size
                    {
                        self.right_rotate(right);
                        self.left_rotate(root);
                    } else {
                        self.dec_size(*root);
                        root = left;
                    }
                } else if self.first_is_to_the_right_of_second(node, *root) {
                    let decremented_right_size = right_size - T::from_byte(1);
                    if self.get_size_or_zero(self.get_left_or_default(*left))
                        > decremented_right_size
                    {
                        self.right_rotate(root);
                    } else if self.get_size_or_zero(self.get_right_or_default(*left))
                        > decremented_right_size
                    {
                        self.left_rotate(left);
                        self.right_rotate(root);
                    } else {
                        self.dec_size(*root);
                        root = right;
                    }
                } else {
                    if left_size > T::from_byte(0) && right_size > T::from_byte(0) {
                        let replacement;
                        if left_size > right_size {
                            replacement = self.get_rightest(*left);
                            self.detach_core(left, replacement);
                        } else {
                            replacement = self.get_leftest(*right);
                            self.detach_core(right, replacement);
                        }
                        self.set_left(replacement, *left);
                        self.set_right(replacement, *right);
                        self.set_size(replacement, left_size + right_size);
                        *root = replacement;
                    } else if left_size > T::from_byte(0) {
                        *root = *left;
                    } else if right_size > T::from_byte(0) {
                        *root = *right;
                    } else {
                        *root = T::from_byte(0);
                    }
                    self.clear_node(node);
                    return;
                }
            }
        }
    }
}