def should_splay(): tree = SplayTree(N(6, N(5, N(4, N(3, N(2, N(1))))))) tree.find(1) assert [1, 2, 3, 4, 5, 6] == inorder(tree.root) assert tree.root.value == 1 tree.delete(4) assert [1, 2, 3, 5, 6] == inorder(tree.root)
def should_rotate_left(): ''' 4 4 | => | ------- ------- / \ / \ 2 6 3 6 | | / | ----- ----- 2 ----- / \ / \ / / \ 1 3 5 7 1 5 7 ''' tree = sample_tree() before_inorder = inorder(tree) rotate_left(tree.left) assert before_inorder == inorder(tree) assert 3 == tree.left.value assert 2 == tree.left.left.value assert 1 == tree.left.left.left.value rotate_right(tree.left) assert sample_tree().equivalent(tree)
def should_delete_double_black(): ''' delete 3 2 2 / \ => / 1 3 (1) 8 | --------- / \ 4 12 | | ---- ---- / \ / \ 2 6 10 14 / \ / \ / \ / \ 1 3 5 7 9 11 13 15 ''' tree1 = N(2, N(1), N(3)) tree1 = delete(3, tree1) assert is_valid(tree1) assert [1, 2] == inorder(tree1) tree2 = N(8, N(4, N(2, N(1), N(3)), N(6, N(5), N(7))), N(12, N(10, N(9), N(11)), N(14, N(13), N(15)))) for i in range(1, 16): print strify(tree2) assert is_valid(tree2) assert range(i, 16) == inorder(tree2) print "remove %s from %s" % (i, strify(tree2)) tree2 = delete(i, tree2) assert not tree2
def should_insert_inorder(): for i in range(5): inputs = list(rand.randint(100, size=35)) print inputs tree = None for j, val in enumerate(inputs): tree = insert(val, tree) values_in_order = inorder(tree) assert j + 1 == len(values_in_order) assert sorted(inputs[0:len(values_in_order)]) == values_in_order assert is_valid(tree) assert sorted(inputs) == inorder(tree)
def should_insert_inorder(): for i in range(5): inputs = list(rand.randint(100, size=35)) print inputs tree = None for j, val in enumerate(inputs): tree = insert(val, tree) values_in_order = inorder(tree) assert j + 1 == len(values_in_order) assert sorted(inputs[0: len(values_in_order)]) == values_in_order assert is_valid(tree) assert sorted(inputs) == inorder(tree)
def should_handle_dups(): tree = SplayTree() elems = [31, 13, 98, 17, 13, 9, 2, 2, 2, 90, 36] for e in elems: tree.insert(e) node = tree.find(98) assert inorder(node) == sorted(elems) assert node.value == 98 assert tree.root.value == 98 for i in range(len(elems)): tree.delete(elems[i]) assert inorder(tree.root) == sorted(elems[i + 1 :]) assert not tree.root
def should_work_for_a_large_tree(): for i in range(10): inputs = list(rand.randint(10000, size=3000)) tree = reduce(lambda tree, val: insert(val, tree), inputs, None) assert is_valid(tree) assert inorder(tree) == sorted(inputs) for i in range(2500): val = inputs.pop() # print "delete %s from tree %s" % (val, strify(tree)) tree = delete(val, tree) # assert is_valid(tree), strify(tree) assert is_valid(tree) assert inorder(tree) == sorted(inputs)
def should_handle_dups(): tree = Tree() elems = [31, 13, 98, 17, 13, 9, 2, 2, 2, 90, 36] for e in elems: tree.insert(e) node = tree.find(98) assert inorder(node) == sorted(elems) assert node.value == 98 assert tree.root.value == 98 for i in range(len(elems)): tree.delete(elems[i]) assert inorder(tree.root) == sorted(elems[i + 1:]) assert not tree.root
def should_delete_with_dups(): tree = N(3, N(1,N(1),N(2), R), N(5,N(4),N(6,right=N(7, color=R)), R)) assert is_valid(tree) tree = delete(1, tree) assert is_valid(tree) assert [1, 2, 3, 4, 5, 6, 7] == inorder(tree)
def should_splay_tree(): n = 20 tree = None for i in range(n): tree = N(i, tree) for j in range(1, n): tree = splay(tree, j) assert tree.value == j assert range(n) == inorder(tree)
def should_splay_tree(): n = 20 tree = None for i in range(n): tree = N(i, tree) for j in range(1, n): tree = splay(tree,j) assert tree.value == j assert range(n) == inorder(tree)
def should_insert_delete(): for i in range(5): #regress 5 times depth_ratio = 0 NO_OF_TREES = 25 for i in range(NO_OF_TREES): tree = Tree() n = rand.randint(50, 250) elems = rand.randint(1, 100, size=n) for e in elems: tree.insert(e) assert inorder(tree.root) == sorted(elems) depth_ratio += depth(tree.root) / numpy.log2(n) for i in range(n // 2): tree.delete(elems[i]) assert inorder(tree.root) == sorted(elems[n // 2:]) depth_ratio += depth(tree.root) / numpy.log2(n // 2) # for NO_OF_TREES*2 no of samples the sample tree depth is atmost 2.5logn # i.e depth is order log(n) for splay trees assert depth_ratio / (NO_OF_TREES * 2) < 2.5
def should_insert_delete(): for i in range(5):#regress 5 times depth_ratio = 0 NO_OF_TREES = 25 for i in range(NO_OF_TREES): tree = Tree() n = rand.randint(50, 250) elems = rand.randint(1, 100, size=n) for e in elems: tree.insert(e) assert inorder(tree.root) == sorted(elems) depth_ratio += depth(tree.root) / numpy.log2(n) for i in range(n // 2): tree.delete(elems[i]) assert inorder(tree.root) == sorted(elems[n//2:]) depth_ratio += depth(tree.root) / numpy.log2(n//2) # for NO_OF_TREES*2 no of samples the sample tree depth is atmost 2.5logn # i.e depth is order log(n) for splay trees assert depth_ratio / (NO_OF_TREES * 2) < 2.5
def should_delete_nodes(): for i in range(3): arr = sorted(random.randint(1000, size=10)) tree = make_tree(arr) while len(arr) > 0: assert inorder(tree) == arr val = arr[random.randint(0, len(arr))] arr.remove(val) tree = delete(tree, val) if len(arr) > 1: assert tree assert not tree
def should_delete_double_black(): ''' delete 3 2 2 / \ => / 1 3 (1) 8 | --------- / \ 4 12 | | ---- ---- / \ / \ 2 6 10 14 / \ / \ / \ / \ 1 3 5 7 9 11 13 15 ''' tree1 = N(2, N(1), N(3)) tree1 = delete(3, tree1) assert is_valid(tree1) assert [1, 2] == inorder(tree1) tree2 =N(8, N(4, N(2, N(1), N(3)), N(6, N(5), N(7))), N(12, N(10, N(9), N(11)), N(14, N(13), N(15)))) for i in range(1, 16): print strify(tree2) assert is_valid(tree2) assert range(i, 16) == inorder(tree2) print "remove %s from %s" % (i, strify(tree2)) tree2 = delete(i, tree2) assert not tree2
def should_delete_from_sample(): ''' 4 | ------- / \ 2 (6) | | ----- ----- / \ / \ (1) (3) 5 7 ''' tree = delete(3, sample_tree()) assert not find(3, tree) assert [1, 2, 4, 5, 6, 7] == inorder(tree) tree = delete(4, sample_tree()) print inorder(tree, 'color') assert is_valid(tree) assert tree.value == 5 assert not tree.right.left assert tree.right.color == B assert tree.right.right.color == R tree = delete(6, sample_tree()) assert is_valid(tree) assert tree.right.color == B assert not tree.right.right assert tree.right.left.color == R assert [5, 7] == inorder(tree.right) tree = delete(5, blackify(sample_tree())) assert is_valid(tree) assert [1, 2, 3, 4, 6, 7] == inorder(tree) assert tree.left.color == R assert tree.right.color == B assert not tree.right.left assert tree.right.right.color == R
def should_rotate_right(): ''' 4 2 | => | ------- ------- / \ / \ 2 6 1 4 | | / \ ----- ----- 3 6 / \ / \ | 1 3 5 7 ----- / \ 5 7 ''' four = sample_tree() rotate_right(four) assert [3, 4, 5, 6, 7] == inorder(four) assert 3 == four.left.value assert four.equivalent(four.left.parent) two = four.parent assert 2 == two.value assert not two.parent # 2 is root original_tree = sample_tree() assert inorder(original_tree) == inorder(two) rotate_left(two) assert four.equivalent(original_tree) assert not four.parent # 4 is root again assert 2 == four.left.value assert 6 == four.right.value three = four.left.right assert 3 == three.value assert 2 == three.parent.value assert 4 == three.parent.parent.value
def should_splay_large_tree(): tree = splay(large_tree(), 12) assert tree.value == 12 assert inorder(tree) == inorder(large_tree())
def should_delete_corner_cases(): ''' delete 4 in this tree Example 1: 3 3 / \ / \ 2 (5) => 2 (7) / / \ / / \ (1) 4 7 (1) 5 8 / \ X \ (6) (8) (4) (6) Example 2: sibling black with single red child. Rotate to romve zig zag (if any) and rotate left. 3 3 3 / \ / \ / \ 2 (5) rotate right 2 (5) left 2 (6) / / \ => / / \ => / / \ (1) 4 7 (1) 4 6 (1) 5 7 / \ X (6) (7) (4) Ex 3: black node, black parent but one of sibling or sibling's children is red 3 | 3 ------- / \ / \ 1 5 1 7 / \ / \ => / \ / \ 1 2 4 (7) 1 2 5 8 / \ X \ 6 8 (4) (6) 3 3 | | 3 ------- ------- / \ / \ => / \ 1 5 1 5 1 6 / \ / \ => / \ / \ / \ / \ 1 2 4 7 1 2 4 6 1 2 5 7 / \ X (6) (7) (4) ''' for tree in [ make_node(3, color=B, left=make_node(2, color=B, left=make_node(1)), right=make_node(5, left=make_node(4, color=B), right=make_node(7, color=B, left=make_node(6), right=make_node(8)))), make_node(3, color=B, left=make_node(1, color=B, left=make_node(1)), right=make_node(5, left=make_node(4, color=B), right=make_node(7, color=B, left=make_node(6)))), make_node(3, color=B, left=make_node(1, color=B, left=make_node(1, color=B), right=make_node(2, color=B)), right=make_node(5, color=B, left=make_node(4, color=B), right=make_node(7, color=B, left=make_node(6), right=make_node(8)))), make_node(3, color=B, left=make_node(1, color=B, left=make_node(1, color=B), right=make_node(2, color=B)), right=make_node(5, color=B, left=make_node(4, color=B), right=make_node(7, color=B, left=make_node(6)))) ]: tree = assign_parents(tree) assert is_valid(tree) # ensure test data is valid vals = inorder(tree) print strify(tree) tree = delete(4, tree) print strify(tree) assert is_valid(tree) vals.remove(4) assert vals == inorder(tree)
def should_splay(): tree = N(6, N(5, N(4, N(3, N(2, N(1)))))) tree = splay(tree, 1) assert tree.value == 1 assert [1, 2, 3, 4, 5, 6] == inorder(tree)
def should_delete_with_dups(): tree = N(3, N(1, N(1), N(2), R), N(5, N(4), N(6, right=N(7, color=R)), R)) assert is_valid(tree) tree = delete(1, tree) assert is_valid(tree) assert [1, 2, 3, 4, 5, 6, 7] == inorder(tree)
def should_delete_node_with_red_sibling(): tree = N(4, N(2, N(1), N(3), R), N(5)) assert is_valid(tree) tree = delete(5, tree) assert is_valid(tree) assert [1, 2, 3, 4] == inorder(tree)
def should_delete_corner_cases(): ''' delete 4 in this tree Example 1: 3 3 / \ / \ 2 (5) => 2 (7) / / \ / / \ (1) 4 7 (1) 5 8 / \ X \ (6) (8) (4) (6) Example 2: sibling black with single red child. Rotate to romve zig zag (if any) and rotate left. 3 3 3 / \ / \ / \ 2 (5) rotate right 2 (5) left 2 (6) / / \ => / / \ => / / \ (1) 4 7 (1) 4 6 (1) 5 7 / \ X (6) (7) (4) Ex 3: black node, black parent but one of sibling or sibling's children is red 3 | 3 ------- / \ / \ 1 5 1 7 / \ / \ => / \ / \ 1 2 4 (7) 1 2 5 8 / \ X \ 6 8 (4) (6) 3 3 | | 3 ------- ------- / \ / \ => / \ 1 5 1 5 1 6 / \ / \ => / \ / \ / \ / \ 1 2 4 7 1 2 4 6 1 2 5 7 / \ X (6) (7) (4) ''' for tree in [ make_node(3, color=B, left=make_node(2, color=B, left=make_node(1)), right = make_node(5, left=make_node(4, color=B), right = make_node(7, color=B, left=make_node(6), right = make_node(8)))), make_node(3, color=B, left=make_node(1, color=B, left=make_node(1)), right = make_node(5, left=make_node(4, color=B), right = make_node(7, color=B, left=make_node(6)))), make_node(3, color=B, left=make_node(1, color=B, left=make_node(1, color=B), right = make_node(2, color =B)), right = make_node(5, color=B, left=make_node(4, color=B), right = make_node(7, color=B, left=make_node(6), right = make_node(8)))), make_node(3, color=B, left=make_node(1, color=B, left=make_node(1, color=B), right = make_node(2, color =B)), right = make_node(5, color=B, left=make_node(4, color=B), right = make_node(7, color=B, left=make_node(6))))]: tree = assign_parents(tree) assert is_valid(tree) # ensure test data is valid vals = inorder(tree) print strify(tree) tree = delete(4, tree) print strify(tree) assert is_valid(tree) vals.remove(4) assert vals == inorder(tree)
def is_valid_binary_tree(tree): values_in_order = inorder(tree) return values_in_order == sorted(values_in_order)
def should_insert_values(): for n in [50, 100, 500, 1000]: a = random.randint(1001, size=n) tree = make_tree(a) assert inorder(tree) == sorted(a)