diff --git a/src/algo/add.rs b/src/algo/add.rs index a25e922..0ddc882 100644 --- a/src/algo/add.rs +++ b/src/algo/add.rs @@ -68,8 +68,11 @@ impl Stack { return self._get::<1>(); } - fn getGrandGrandParent(&self) -> &T { - return self._get::<2>(); + fn getGrandGrandParent(&self) -> Option<&T> { + match self.hasGrandGrandParent() { + false => None, + true => Some(self._get::<2>()), + } } fn pop(&mut self) -> T { @@ -173,7 +176,23 @@ fn _add_recursive( unsafe { balance(ctx, stack) } } -unsafe fn balance(ctx: &mut Ctx, stack: &mut Stack>) { +trait DirectedBalancingContext: + RedBlackTreeColorContext + DirectedBinaryTreeChildrenGetterContext +{ + fn rotateForward_Forward(&mut self, parent: Self::NodeRef, pivot: Self::NodeRef); + fn rotateOpposite( + &mut self, + parent: Option<(Self::NodeRef, BinaryTreeDirection)>, + pivot: Self::NodeRef, + ); +} +trait BalancingContext: RedBlackTreeColorContext { + fn getLeftDirectedContext(&mut self) -> impl DirectedBalancingContext; + fn getRightDirectedContext(&mut self) + -> impl DirectedBalancingContext; +} + +unsafe fn balance(ctx: &mut Ctx, stack: &mut Stack>) { loop { if ctx.getColor(stack.getParent().node.clone()) == Color::BLACK { break; @@ -183,36 +202,57 @@ unsafe fn balance(ctx: &mut Ctx, stack: &mut Stack { + if _directed(&mut ctx.getLeftDirectedContext(), stack) { + break; + } + } + BinaryTreeDirection::RIGHT => { + if _directed(&mut ctx.getRightDirectedContext(), stack) { break; } - stack.popDiscard(); - stack.popDiscard(); - continue; } } - if stack.getGrandParent().dir != stack.getParent().dir { - todo!("__rotateForward_Forward(parent, grandParent)"); - stack.replaceTop(Frame { - node: stack.getParent().node, - dir: stack.getGrandParent().dir, - }) - } - ctx.setColor(stack.getParent().node.clone(), Color::BLACK); - ctx.setColor(stack.getGrandParent().node.clone(), Color::RED); - todo!("__rotateOpposite_Switch(grandParent)"); + fn _directed( + ctx: &mut Ctx, + stack: &mut Stack>, + ) -> bool { + let uncle = ctx.getOppositeChild(stack.getGrandParent().node.clone()); + if let Some(uncle) = uncle { + if ctx.getColor(uncle.clone()) == Color::RED { + ctx.setColor(stack.getParent().node.clone(), Color::BLACK); + ctx.setColor(uncle, Color::BLACK); + ctx.setColor(stack.getGrandParent().node.clone(), Color::RED); - break; + if !stack.hasGrandGrandParent() { + return true; + } + stack.popDiscard(); + stack.popDiscard(); + return false; + } + } + + if stack.getGrandParent().dir != stack.getParent().dir { + ctx.rotateForward_Forward( + stack.getGrandParent().node.clone(), + stack.getParent().node.clone(), + ); + stack.replaceTop(Frame { + node: stack.getParent().node.clone(), + dir: stack.getGrandParent().dir, + }) + } + ctx.setColor(stack.getParent().node.clone(), Color::BLACK); + ctx.setColor(stack.getGrandParent().node.clone(), Color::RED); + ctx.rotateOpposite( + stack.getGrandGrandParent().map(|f| (f.node.clone(), f.dir)), + stack.getGrandParent().node.clone(), + ); + + return true; + } } }