def effective_os_delete(T, z): if z.left is T.nil or z.right is T.nil: y = z else: y = rb_successor(z, T.nil) p = rb_predecessor(y, T.nil) s = rb_successor(y, T.nil) if y.left is not T.nil: x = y.left else: x = y.right x.p = y.p if y.p is T.nil: T.root = x else: if y is y.p.left: y.p.left = x else: y.p.right = x if y is not z: z.key = y.key z.data = y.data w = x.p while w is not T.nil: _update_additional_fields(T, w) w = w.p if y.color == Black: effective_os_delete_fixup(T, x) if p is not T.nil: p.succ = s if s is not T.nil: s.pred = p return y
def test_effective_os_tree(self): _, keys = get_random_array() tree = RedBlackTree(sentinel=OSNode(None)) tree.nil.min = tree.nil.max = tree.nil.pred = tree.nil.succ = tree.nil for key in keys: effective_os_insert(tree, OSNode(key)) nodes = get_binary_tree_nodes(tree, sentinel=tree.nil) while nodes: actual_minimum = effective_os_minimum(tree) actual_maximum = effective_os_maximum(tree) expected_minimum = rb_minimum(tree.root, sentinel=tree.nil) expected_maximum = rb_maximum(tree.root, sentinel=tree.nil) assert_that(actual_minimum, is_(expected_minimum)) assert_that(actual_maximum, is_(expected_maximum)) node = random.choice(nodes) actual_predecessor = effective_os_predecessor(tree, node) actual_successor = effective_os_successor(tree, node) expected_predecessor = rb_predecessor(node, sentinel=tree.nil) expected_successor = rb_successor(node, sentinel=tree.nil) assert_that(actual_predecessor, is_(expected_predecessor)) assert_that(actual_successor, is_(expected_successor)) effective_os_delete(tree, node) nodes = get_binary_tree_nodes(tree, sentinel=tree.nil)
def os_delete(T, z): if z.left is T.nil or z.right is T.nil: y = z else: y = rb_successor(z, T.nil) if y.left is not T.nil: x = y.left else: x = y.right x.p = y.p if y.p is T.nil: T.root = x else: if y is y.p.left: y.p.left = x else: y.p.right = x if y is not z: z.key = y.key z.data = y.data w = x.p while w is not T.nil: w.size -= 1 w = w.p if y.color == Black: os_delete_fixup(T, x) return y
def _interval_pom_delete(T, z): if z.left is T.nil or z.right is T.nil: y = z else: y = rb_successor(z, sentinel=T.nil) if y.left is not T.nil: x = y.left else: x = y.right x.p = y.p if y.p is T.nil: T.root = x else: if y is y.p.left: y.p.left = x else: y.p.right = x if y is not z: z.key = y.key z.data = y.data z.low = y.low z.high = y.high w = x.p while w is not T.nil: _update_additional_fields(w) w = w.p if y.color == Black: _interval_pom_delete_fixup(T, x) return y
def effective_os_insert(T, z): y = T.nil x = T.root while x is not T.nil: y = x if z.key < x.key: x = x.left else: x = x.right z.p = y if y is T.nil: T.root = z else: if z.key < y.key: y.left = z else: y.right = z z.left = z.right = T.nil z.color = Red z.size = 1 z.min = z.max = z x = y while x is not T.nil: _update_additional_fields(T, x) x = x.p effective_os_insert_fixup(T, z) z.pred = rb_predecessor(z, sentinel=T.nil) if z.pred is not T.nil: z.pred.succ = z z.succ = rb_successor(z, sentinel=T.nil) if z.succ is not T.nil: z.succ.pred = z
def joinable_rb_delete(T, z): if z.left is None or z.right is None: y = z else: y = rb_successor(z) if y.left is not None: x = y.left else: x = y.right if x is None: x = Node(None) # create a dummy node that will mimic sentinel x.p = y.p if y.p is None: T.root = x else: if y is y.p.left: y.p.left = x else: y.p.right = x if y is not z: z.key = y.key z.data = y.data if y.color == Black: joinable_rb_delete_fixup(T, x) if x.key is None: # if x is the dummy node replace it with None if x is T.root: T.root = None T.bh = 0 else: if x is x.p.left: x.p.left = None else: x.p.right = None return y
def min_gap_delete(Q, z): if z.left is Q.nil or z.right is Q.nil: y = z else: y = rb_successor(z, sentinel=Q.nil) if y.left is not Q.nil: x = y.left else: x = y.right x.p = y.p if y.p is Q.nil: Q.root = x else: if y is y.p.left: y.p.left = x else: y.p.right = x if y is not z: z.key = y.key z.data = y.data w = x.p while w is not Q.nil: _update_additional_fields(w) w = w.p if y.color == Black: min_gap_delete_fixup(Q, x) return y
def rb_delete(T, z, sentinel=None): if z.left is sentinel or z.right is sentinel: y = z else: y = rb_successor(z, sentinel) if y.left is not sentinel: x = y.left else: x = y.right x.p = y.p if y.p is sentinel: T.root = x else: if y is y.p.left: y.p.left = x else: y.p.right = x if y is not z: z.key = y.key z.data = y.data if y.color == Black: rb_delete_fixup(T, x, sentinel) return y
def persistent_rb_delete(T, z): T_ = RedBlackTree() T_.root = T_.nil = T.nil if z.left is T.nil or z.right is T.nil: y = z else: y = rb_successor(z, T.nil) path_length = _get_path_length_from_root_to_node(T, y) S = Array.indexed(1, path_length + 1) S.top = 0 p = T.root r = T.nil p_ = r_ = T_.nil push(S, p_) z_ = T.nil while p is not y: p_ = rb.ParentlessNode.clone(p) push(S, p_) if p is z: z_ = p_ if r_ is T_.nil: T_.root = p_ else: if p is r_.left: r_.left = p_ else: r_.right = p_ r = p r_ = p_ if y.key < p.key: p = p.left else: p = p.right if y.left is not T.nil: x = y.left else: x = y.right if y.color == Black: if x is not T.nil: x_ = rb.ParentlessNode.clone(x) else: x_ = T.nil if y is T.root: T_.root = x_ else: if y is r.left: p_.left = x_ else: p_.right = x_ if y is not z: z_.key = y.key z_.data = y.data persistent_rb_delete_fixup(T_, S, x_) else: if y is r.left: p_.left = x else: p_.right = x if y is not z: z_.key = y.key z_.data = y.data return T_