Cleaning up 'add' algorithm, naming and publishing
This commit is contained in:
parent
ba1a8d0533
commit
e6fb9bf061
@ -1,79 +0,0 @@
|
|||||||
fun balanceAfterLinking(node: NODE) {
|
|
||||||
this._setColor(node, Color.RED)
|
|
||||||
var current: NODE = node
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
val parent = this._getParent(current)
|
|
||||||
if (parent == null) {
|
|
||||||
current.__assertIsRoot()
|
|
||||||
this._setColor(current, Color.BLACK)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (this._getColor(parent) == Color.BLACK) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
val grandParent = this._getParent(parent)
|
|
||||||
if (grandParent == null) {
|
|
||||||
parent.__assertIsRoot()
|
|
||||||
this._setColor(parent, Color.BLACK)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
this._checkSame(parent, this._getLeftChild(grandParent)) -> {
|
|
||||||
val uncle = this._getRightChild(grandParent)
|
|
||||||
if (uncle != null && this._getColor(uncle) == Color.RED) {
|
|
||||||
this._setColor(parent, Color.BLACK)
|
|
||||||
this._setColor(uncle, Color.BLACK)
|
|
||||||
this._setColor(grandParent, Color.RED)
|
|
||||||
current = grandParent
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
this._checkSame(current, this._getLeftChild(parent)) -> {
|
|
||||||
this.__rotateRight_Switch(grandParent)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
this._checkSame(current, this._getRightChild(parent)) -> {
|
|
||||||
this.__rotateLeft_Left(parent, grandParent)
|
|
||||||
current = parent
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> this.__throwTreeCorruptedNotChild(current, parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._checkSame(parent, this._getRightChild(grandParent)) -> {
|
|
||||||
val uncle = this._getLeftChild(grandParent)
|
|
||||||
if (uncle != null && this._getColor(uncle) == Color.RED) {
|
|
||||||
this._setColor(parent, Color.BLACK)
|
|
||||||
this._setColor(uncle, Color.BLACK)
|
|
||||||
this._setColor(grandParent, Color.RED)
|
|
||||||
current = grandParent
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
when {
|
|
||||||
this._checkSame(current, this._getRightChild(parent)) -> {
|
|
||||||
this.__rotateLeft_Switch(grandParent)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
this._checkSame(current, this._getLeftChild(parent)) -> {
|
|
||||||
this.__rotateRight_Right(parent, grandParent)
|
|
||||||
current = parent
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> this.__throwTreeCorruptedNotChild(current, parent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> this.__throwTreeCorruptedNotChild(parent, grandParent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
153
src/algo/add.rs
153
src/algo/add.rs
@ -1,5 +1,4 @@
|
|||||||
use crate::context::{Color, RedBlackTreeColorContext};
|
use crate::context::{Color, RedBlackTreeColorContext};
|
||||||
use binary_tree_core_0::NodeRefContainer;
|
|
||||||
use binary_tree_core_0::base_context::{
|
use binary_tree_core_0::base_context::{
|
||||||
BinaryTreeChildrenGetterContext, BinaryTreeDirection, BinaryTreeDirectionDispatcherClojure,
|
BinaryTreeChildrenGetterContext, BinaryTreeDirection, BinaryTreeDirectionDispatcherClojure,
|
||||||
BinaryTreeRootGetter,
|
BinaryTreeRootGetter,
|
||||||
@ -10,109 +9,27 @@ use binary_tree_core_0::directed_context::{
|
|||||||
use binary_tree_core_0::relation_context::{
|
use binary_tree_core_0::relation_context::{
|
||||||
BinaryTreeRelationSetterContext, BinaryTreeRootRelationSetterContext,
|
BinaryTreeRelationSetterContext, BinaryTreeRootRelationSetterContext,
|
||||||
};
|
};
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
pub trait AddRecContext:
|
pub trait RedBlackTreeAddingContext:
|
||||||
BinaryTreeRootGetter
|
BinaryTreeRootGetter
|
||||||
+ BinaryTreeChildrenGetterContext
|
|
||||||
+ BinaryTreeRootRelationSetterContext
|
+ BinaryTreeRootRelationSetterContext
|
||||||
+ BinaryTreeRelationSetterContext
|
+ BinaryTreeRelationSetterContext
|
||||||
+ BinaryTreeDirectionDispatcherClojure
|
|
||||||
+ RedBlackTreeColorContext
|
+ RedBlackTreeColorContext
|
||||||
{
|
{
|
||||||
|
fn getLinkingContext(
|
||||||
|
&mut self,
|
||||||
|
) -> impl RedBlackTreeAddingContext_Linking<NodeRef = Self::NodeRef>;
|
||||||
|
fn getBalancingContext(
|
||||||
|
&mut self,
|
||||||
|
) -> impl RedBlackTreeAddingContext_Balancing<NodeRef = Self::NodeRef>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Frame<NodeRef> {
|
pub struct ParentInfo<NodeRef: binary_tree_core_0::NodeRef> {
|
||||||
node: NodeRef,
|
node: NodeRef,
|
||||||
dir: BinaryTreeDirection,
|
dir: BinaryTreeDirection,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Stack<T> {
|
pub fn add<Ctx: RedBlackTreeAddingContext>(ctx: &mut Ctx, newNode: Ctx::NodeRef) {
|
||||||
start: NonNull<T>,
|
|
||||||
ptr: NonNull<T>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Stack<T> {
|
|
||||||
fn init<const SIZE: usize>(buffer: &mut [MaybeUninit<T>; SIZE]) -> Self {
|
|
||||||
unsafe {
|
|
||||||
let start = NonNull::new_unchecked(
|
|
||||||
((*buffer.as_mut_ptr()).as_mut_ptr())
|
|
||||||
.offset(const { 0isize.strict_add_unsigned(SIZE) }),
|
|
||||||
);
|
|
||||||
return Self { start, ptr: start };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn push(&mut self, value: T) {
|
|
||||||
unsafe {
|
|
||||||
let newPtr = self.ptr.offset(-1);
|
|
||||||
newPtr.as_ptr().write(value);
|
|
||||||
self.ptr = newPtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _get<const OFFSET: usize>(&self) -> &T {
|
|
||||||
unsafe {
|
|
||||||
let loc = self
|
|
||||||
.ptr
|
|
||||||
.offset(const { 0isize.strict_add_unsigned(OFFSET) });
|
|
||||||
return loc.as_ref();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn getParent(&self) -> &T {
|
|
||||||
return self._get::<0>();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getGrandParent(&self) -> &T {
|
|
||||||
return self._get::<1>();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getGrandGrandParent(&self) -> Option<&T> {
|
|
||||||
match self.hasGrandGrandParent() {
|
|
||||||
false => None,
|
|
||||||
true => Some(self._get::<2>()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop(&mut self) -> T {
|
|
||||||
unsafe {
|
|
||||||
let newPtr = self.ptr.offset(1);
|
|
||||||
let value = self.ptr.read();
|
|
||||||
self.ptr = newPtr;
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn popDiscard(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
self.ptr = self.ptr.offset(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fn replaceTop(&mut self, value: T) {
|
|
||||||
unsafe {
|
|
||||||
self.ptr.write(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn _has<const OFFSET: usize>(&self) -> bool {
|
|
||||||
unsafe {
|
|
||||||
return self
|
|
||||||
.ptr
|
|
||||||
.offset(const { 0isize.strict_add_unsigned(OFFSET) })
|
|
||||||
< self.start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn hasGrandParent(&self) -> bool {
|
|
||||||
return self._has::<1>();
|
|
||||||
}
|
|
||||||
fn hasGrandGrandParent(&self) -> bool {
|
|
||||||
return self._has::<2>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_recursive<Ctx: AddRecContext>(ctx: &mut Ctx, newNode: Ctx::NodeRef) {
|
|
||||||
ctx.clearLeftChild(newNode.clone());
|
ctx.clearLeftChild(newNode.clone());
|
||||||
ctx.clearRightChild(newNode.clone());
|
ctx.clearRightChild(newNode.clone());
|
||||||
ctx.setColor(newNode.clone(), Color::RED);
|
ctx.setColor(newNode.clone(), Color::RED);
|
||||||
@ -125,13 +42,13 @@ pub fn add_recursive<Ctx: AddRecContext>(ctx: &mut Ctx, newNode: Ctx::NodeRef) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Some(root) => {
|
Some(root) => {
|
||||||
link(ctx, root, newNode);
|
_link(&mut ctx.getLinkingContext(), root, newNode);
|
||||||
balance(ctx);
|
_balance(&mut ctx.getBalancingContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait LinkingContext:
|
pub trait RedBlackTreeAddingContext_Linking:
|
||||||
BinaryTreeChildrenGetterContext
|
BinaryTreeChildrenGetterContext
|
||||||
+ BinaryTreeRelationSetterContext
|
+ BinaryTreeRelationSetterContext
|
||||||
+ BinaryTreeDirectionDispatcherClojure
|
+ BinaryTreeDirectionDispatcherClojure
|
||||||
@ -139,7 +56,11 @@ trait LinkingContext:
|
|||||||
fn stackAddParentInfo(&mut self, node: Self::NodeRef, dir: BinaryTreeDirection);
|
fn stackAddParentInfo(&mut self, node: Self::NodeRef, dir: BinaryTreeDirection);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn link<Ctx: LinkingContext>(ctx: &mut Ctx, mut it: Ctx::NodeRef, newNode: Ctx::NodeRef) {
|
fn _link<Ctx: RedBlackTreeAddingContext_Linking>(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
mut it: Ctx::NodeRef,
|
||||||
|
newNode: Ctx::NodeRef,
|
||||||
|
) {
|
||||||
loop {
|
loop {
|
||||||
let dir = ctx
|
let dir = ctx
|
||||||
.determineDirection(it.clone())
|
.determineDirection(it.clone())
|
||||||
@ -166,22 +87,25 @@ fn link<Ctx: LinkingContext>(ctx: &mut Ctx, mut it: Ctx::NodeRef, newNode: Ctx::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait BalancingContext: RedBlackTreeColorContext {
|
pub trait RedBlackTreeAddingContext_Balancing: RedBlackTreeColorContext {
|
||||||
fn getLeftDirectedContext(&mut self) -> impl DirectedBalancingContext<NodeRef = Self::NodeRef>;
|
fn getLeftDirectedContext(
|
||||||
fn getRightDirectedContext(&mut self)
|
&mut self,
|
||||||
-> impl DirectedBalancingContext<NodeRef = Self::NodeRef>;
|
) -> impl RedBlackTreeAddingContext_DirectedBalancing<NodeRef = Self::NodeRef>;
|
||||||
|
fn getRightDirectedContext(
|
||||||
|
&mut self,
|
||||||
|
) -> impl RedBlackTreeAddingContext_DirectedBalancing<NodeRef = Self::NodeRef>;
|
||||||
|
|
||||||
fn stackPopParentInfo(&self) -> Option<Frame<Self::NodeRef>>;
|
fn stackPopParentInfo(&self) -> Option<ParentInfo<Self::NodeRef>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DirectedBalancingContext:
|
pub trait RedBlackTreeAddingContext_DirectedBalancing:
|
||||||
RedBlackTreeColorContext + DirectedBinaryTreeChildrenGetterContext
|
RedBlackTreeColorContext + DirectedBinaryTreeChildrenGetterContext
|
||||||
{
|
{
|
||||||
fn rotateForward_Forward(&mut self, parent: Self::NodeRef, pivot: Self::NodeRef);
|
fn rotateForward_Forward(&mut self, parent: Self::NodeRef, pivot: Self::NodeRef);
|
||||||
fn rotateOpposite_GrandParent(&mut self, pivot: Self::NodeRef);
|
fn rotateOpposite_GrandParent(&mut self, pivot: Self::NodeRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn balance<Ctx: BalancingContext>(ctx: &mut Ctx) {
|
fn _balance<Ctx: RedBlackTreeAddingContext_Balancing>(ctx: &mut Ctx) {
|
||||||
loop {
|
loop {
|
||||||
let parent;
|
let parent;
|
||||||
match ctx.stackPopParentInfo() {
|
match ctx.stackPopParentInfo() {
|
||||||
@ -215,10 +139,10 @@ fn balance<Ctx: BalancingContext>(ctx: &mut Ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _directed<Ctx: DirectedBalancingContext>(
|
fn _directed<Ctx: RedBlackTreeAddingContext_DirectedBalancing>(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
grandparent: Frame<Ctx::NodeRef>,
|
grandparent: ParentInfo<Ctx::NodeRef>,
|
||||||
parent: Frame<Ctx::NodeRef>,
|
parent: ParentInfo<Ctx::NodeRef>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let uncle = ctx.getOppositeChild(grandparent.node.clone());
|
let uncle = ctx.getOppositeChild(grandparent.node.clone());
|
||||||
if let Some(uncle) = uncle {
|
if let Some(uncle) = uncle {
|
||||||
@ -233,7 +157,7 @@ fn balance<Ctx: BalancingContext>(ctx: &mut Ctx) {
|
|||||||
|
|
||||||
let normalizedParent;
|
let normalizedParent;
|
||||||
if grandparent.dir != parent.dir {
|
if grandparent.dir != parent.dir {
|
||||||
normalizedParent = Frame {
|
normalizedParent = ParentInfo {
|
||||||
node: ctx.getOppositeChild(parent.node.clone()).unwrap(),
|
node: ctx.getOppositeChild(parent.node.clone()).unwrap(),
|
||||||
dir: grandparent.dir,
|
dir: grandparent.dir,
|
||||||
};
|
};
|
||||||
@ -250,3 +174,18 @@ fn balance<Ctx: BalancingContext>(ctx: &mut Ctx) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn balanceAfterLinking<
|
||||||
|
Ctx: RedBlackTreeAddingContext_Balancing + BinaryTreeRelationSetterContext + BinaryTreeRootGetter,
|
||||||
|
>(
|
||||||
|
ctx: &mut Ctx,
|
||||||
|
newNode: Ctx::NodeRef,
|
||||||
|
) {
|
||||||
|
ctx.clearLeftChild(newNode.clone());
|
||||||
|
ctx.clearRightChild(newNode.clone());
|
||||||
|
ctx.setColor(newNode.clone(), Color::RED);
|
||||||
|
|
||||||
|
_balance(ctx);
|
||||||
|
|
||||||
|
ctx.setColor(ctx.getRoot().unwrap(), Color::BLACK)
|
||||||
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
mod add;
|
pub mod add;
|
||||||
@ -1,4 +1,4 @@
|
|||||||
mod algo;
|
pub mod algo;
|
||||||
mod context;
|
pub mod context;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user