Redesigned balancing without explicit using stack
This commit is contained in:
parent
2303585d5e
commit
1dd64086db
@ -173,43 +173,53 @@ fn _add_recursive<Ctx: AddRecContext>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe { balance(ctx, stack) }
|
unsafe { balance(ctx) }
|
||||||
|
}
|
||||||
|
|
||||||
|
trait BalancingContext: RedBlackTreeColorContext {
|
||||||
|
fn getLeftDirectedContext(&mut self) -> impl DirectedBalancingContext<NodeRef = Self::NodeRef>;
|
||||||
|
fn getRightDirectedContext(&mut self)
|
||||||
|
-> impl DirectedBalancingContext<NodeRef = Self::NodeRef>;
|
||||||
|
|
||||||
|
fn stackPopParentInfo(&self) -> Option<Frame<Self::NodeRef>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait DirectedBalancingContext:
|
trait DirectedBalancingContext:
|
||||||
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(
|
fn rotateOpposite_GrandParent(&mut self, pivot: Self::NodeRef);
|
||||||
&mut self,
|
|
||||||
parent: Option<(Self::NodeRef, BinaryTreeDirection)>,
|
|
||||||
pivot: Self::NodeRef,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
trait BalancingContext: RedBlackTreeColorContext {
|
|
||||||
fn getLeftDirectedContext(&mut self) -> impl DirectedBalancingContext<NodeRef = Self::NodeRef>;
|
|
||||||
fn getRightDirectedContext(&mut self)
|
|
||||||
-> impl DirectedBalancingContext<NodeRef = Self::NodeRef>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn balance<Ctx: BalancingContext>(ctx: &mut Ctx, stack: &mut Stack<Frame<Ctx::NodeRef>>) {
|
fn balance<Ctx: BalancingContext>(ctx: &mut Ctx) {
|
||||||
loop {
|
loop {
|
||||||
if ctx.getColor(stack.getParent().node.clone()) == Color::BLACK {
|
let parent;
|
||||||
break;
|
match ctx.stackPopParentInfo() {
|
||||||
|
None => return,
|
||||||
|
Some(_parent) => parent = _parent,
|
||||||
}
|
}
|
||||||
if !stack.hasGrandParent() {
|
|
||||||
ctx.setColor(stack.getParent().node.clone(), Color::BLACK);
|
if ctx.getColor(parent.node.clone()) == Color::BLACK {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
match stack.getGrandParent().dir {
|
let grandparent;
|
||||||
|
match ctx.stackPopParentInfo() {
|
||||||
|
None => {
|
||||||
|
ctx.setColor(parent.node.clone(), Color::BLACK);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Some(_grandparent) => grandparent = _grandparent,
|
||||||
|
}
|
||||||
|
|
||||||
|
match grandparent.dir {
|
||||||
BinaryTreeDirection::LEFT => {
|
BinaryTreeDirection::LEFT => {
|
||||||
if _directed(&mut ctx.getLeftDirectedContext(), stack) {
|
if _directed(&mut ctx.getLeftDirectedContext(), grandparent, parent) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BinaryTreeDirection::RIGHT => {
|
BinaryTreeDirection::RIGHT => {
|
||||||
if _directed(&mut ctx.getRightDirectedContext(), stack) {
|
if _directed(&mut ctx.getRightDirectedContext(), grandparent, parent) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,40 +227,34 @@ unsafe fn balance<Ctx: BalancingContext>(ctx: &mut Ctx, stack: &mut Stack<Frame<
|
|||||||
|
|
||||||
fn _directed<Ctx: DirectedBalancingContext>(
|
fn _directed<Ctx: DirectedBalancingContext>(
|
||||||
ctx: &mut Ctx,
|
ctx: &mut Ctx,
|
||||||
stack: &mut Stack<Frame<Ctx::NodeRef>>,
|
grandparent: Frame<Ctx::NodeRef>,
|
||||||
|
parent: Frame<Ctx::NodeRef>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let uncle = ctx.getOppositeChild(stack.getGrandParent().node.clone());
|
let uncle = ctx.getOppositeChild(grandparent.node.clone());
|
||||||
if let Some(uncle) = uncle {
|
if let Some(uncle) = uncle {
|
||||||
if ctx.getColor(uncle.clone()) == Color::RED {
|
if ctx.getColor(uncle.clone()) == Color::RED {
|
||||||
ctx.setColor(stack.getParent().node.clone(), Color::BLACK);
|
ctx.setColor(parent.node.clone(), Color::BLACK);
|
||||||
ctx.setColor(uncle, Color::BLACK);
|
ctx.setColor(uncle, Color::BLACK);
|
||||||
ctx.setColor(stack.getGrandParent().node.clone(), Color::RED);
|
ctx.setColor(grandparent.node.clone(), Color::RED);
|
||||||
|
|
||||||
if !stack.hasGrandGrandParent() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
stack.popDiscard();
|
|
||||||
stack.popDiscard();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if stack.getGrandParent().dir != stack.getParent().dir {
|
let normalizedParent;
|
||||||
ctx.rotateForward_Forward(
|
if grandparent.dir != parent.dir {
|
||||||
stack.getGrandParent().node.clone(),
|
normalizedParent = Frame {
|
||||||
stack.getParent().node.clone(),
|
node: ctx.getOppositeChild(parent.node.clone()).unwrap(),
|
||||||
);
|
dir: grandparent.dir,
|
||||||
stack.replaceTop(Frame {
|
};
|
||||||
node: stack.getParent().node.clone(),
|
ctx.rotateForward_Forward(grandparent.node.clone(), parent.node.clone());
|
||||||
dir: stack.getGrandParent().dir,
|
let _ = parent;
|
||||||
})
|
} else {
|
||||||
|
normalizedParent = parent;
|
||||||
}
|
}
|
||||||
ctx.setColor(stack.getParent().node.clone(), Color::BLACK);
|
ctx.setColor(normalizedParent.node.clone(), Color::BLACK);
|
||||||
ctx.setColor(stack.getGrandParent().node.clone(), Color::RED);
|
ctx.setColor(grandparent.node.clone(), Color::RED);
|
||||||
ctx.rotateOpposite(
|
ctx.rotateOpposite_GrandParent(grandparent.node.clone());
|
||||||
stack.getGrandGrandParent().map(|f| (f.node.clone(), f.dir)),
|
|
||||||
stack.getGrandParent().node.clone(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user