fix(wavl): propagate root rotation to the helper functions for delete
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
457ab180d0
commit
2433928d36
1 changed files with 27 additions and 27 deletions
54
wavl.py
54
wavl.py
|
@ -29,15 +29,16 @@ class WAVLTree(AVLTree[T]):
|
||||||
|
|
||||||
# region DeleteRebalance
|
# region DeleteRebalance
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def __fix_delete(
|
def __fix_delete(
|
||||||
|
self,
|
||||||
x: Optional[Node[T]],
|
x: Optional[Node[T]],
|
||||||
y: Node[T],
|
y: Node[T],
|
||||||
z: Node[T],
|
z: Node[T],
|
||||||
reversed: bool,
|
reversed: bool,
|
||||||
|
rotating_around_root: bool,
|
||||||
rotate_left: RotateFunction[T],
|
rotate_left: RotateFunction[T],
|
||||||
rotate_right: RotateFunction[T],
|
rotate_right: RotateFunction[T],
|
||||||
) -> Optional[Node[T]]:
|
) -> None:
|
||||||
new_root = x
|
new_root = x
|
||||||
v = y.left
|
v = y.left
|
||||||
w = y.right
|
w = y.right
|
||||||
|
@ -54,6 +55,8 @@ class WAVLTree(AVLTree[T]):
|
||||||
if w_diff == 1 and y.parent:
|
if w_diff == 1 and y.parent:
|
||||||
logger.debug(f"y.parent = {y.parent}")
|
logger.debug(f"y.parent = {y.parent}")
|
||||||
new_root = rotate_left(y.parent)
|
new_root = rotate_left(y.parent)
|
||||||
|
if rotating_around_root:
|
||||||
|
self.root = new_root
|
||||||
|
|
||||||
y.promote()
|
y.promote()
|
||||||
z.demote()
|
z.demote()
|
||||||
|
@ -64,13 +67,13 @@ class WAVLTree(AVLTree[T]):
|
||||||
logger.debug(f"v.parent = {v.parent}")
|
logger.debug(f"v.parent = {v.parent}")
|
||||||
rotate_right(v.parent)
|
rotate_right(v.parent)
|
||||||
new_root = rotate_left(v.parent)
|
new_root = rotate_left(v.parent)
|
||||||
|
if rotating_around_root:
|
||||||
|
self.root = new_root
|
||||||
|
|
||||||
v.promote().promote()
|
v.promote().promote()
|
||||||
y.demote()
|
y.demote()
|
||||||
z.demote().demote()
|
z.demote().demote()
|
||||||
|
|
||||||
return new_root
|
|
||||||
|
|
||||||
def __bottomup_delete(
|
def __bottomup_delete(
|
||||||
self, x: Optional[Node[T]], parent: Optional[Node[T]]
|
self, x: Optional[Node[T]], parent: Optional[Node[T]]
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -104,57 +107,54 @@ class WAVLTree(AVLTree[T]):
|
||||||
return
|
return
|
||||||
|
|
||||||
rotating_around_root = parent.parent is None
|
rotating_around_root = parent.parent is None
|
||||||
new_root: Optional[Node[T]] = parent
|
|
||||||
|
|
||||||
parent_node_diffs = Node.differences(parent)
|
parent_node_diffs = Node.differences(parent)
|
||||||
if parent_node_diffs in ((1, 3), (3, 1)):
|
if parent_node_diffs in ((1, 3), (3, 1)):
|
||||||
if parent.left is x:
|
if parent.left is x:
|
||||||
assert parent.right
|
assert parent.right
|
||||||
new_root = WAVLTree.__fix_delete(
|
self.__fix_delete(
|
||||||
x,
|
x,
|
||||||
parent.right,
|
parent.right,
|
||||||
parent,
|
parent,
|
||||||
False,
|
False,
|
||||||
|
rotating_around_root,
|
||||||
Node.rotate_left,
|
Node.rotate_left,
|
||||||
Node.rotate_right,
|
Node.rotate_right,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
assert parent.left
|
assert parent.left
|
||||||
new_root = WAVLTree.__fix_delete(
|
self.__fix_delete(
|
||||||
x,
|
x,
|
||||||
parent.left,
|
parent.left,
|
||||||
parent,
|
parent,
|
||||||
True,
|
True,
|
||||||
|
rotating_around_root,
|
||||||
Node.rotate_right,
|
Node.rotate_right,
|
||||||
Node.rotate_left,
|
Node.rotate_left,
|
||||||
)
|
)
|
||||||
|
|
||||||
if rotating_around_root:
|
|
||||||
self.root = new_root
|
|
||||||
|
|
||||||
def __delete_fixup(
|
def __delete_fixup(
|
||||||
self, y: Optional[Node[T]], parent: Optional[Node[T]] = None
|
self, y: Optional[Node[T]], parent: Optional[Node[T]] = None
|
||||||
) -> None:
|
) -> None:
|
||||||
logger.debug(f"[__delete_fixup] y = {y}, parent = {parent}")
|
logger.debug(f"[__delete_fixup] y = {y}, parent = {parent}")
|
||||||
|
|
||||||
z = y if y else parent
|
if Node.differences(y) == (2, 2):
|
||||||
logger.debug(
|
y.demote()
|
||||||
f"[z.demote()] Node.differences({repr(z)}) == (2, 2) ~>*"
|
parent = y.parent
|
||||||
f"{Node.differences(z)} == (2, 2)"
|
elif Node.differences(parent) == (2, 2):
|
||||||
)
|
parent.demote()
|
||||||
assert z
|
parent = parent.parent
|
||||||
# FIXME: In combination with propagation below, we get AVL tree
|
|
||||||
if Node.differences(z) == (2, 2):
|
|
||||||
z.demote()
|
|
||||||
|
|
||||||
if parent:
|
if not parent:
|
||||||
for y in (parent.left, parent.right):
|
return
|
||||||
logger.debug(
|
|
||||||
f"[bottom-up delete] Node.difference({y}, {parent}) == 3"
|
for y in (parent.left, parent.right):
|
||||||
f"~>* {Node.difference(y, parent)} == 3"
|
logger.debug(
|
||||||
)
|
f"[bottom-up delete] Node.difference({y}, {parent}) == 3"
|
||||||
if Node.difference(y, parent) == 3:
|
f"~>* {Node.difference(y, parent)} == 3"
|
||||||
self.__bottomup_delete(y, parent)
|
)
|
||||||
|
if Node.difference(y, parent) == 3:
|
||||||
|
self.__bottomup_delete(y, parent)
|
||||||
|
|
||||||
def _delete_rebalance(
|
def _delete_rebalance(
|
||||||
self, node: Optional[Node[T]], parent: Optional[Node[T]]
|
self, node: Optional[Node[T]], parent: Optional[Node[T]]
|
||||||
|
|
Loading…
Reference in a new issue