def setUp(self): # The keys are unique house numbers in a street. # The values are the names of inhabitants. self.houses = [number for number in range(31, 36)] self.people = ['Jane', 'John', 'Ann', 'Bob', 'John'] # Create trees for the tests to use. # A brand new tree. self.new = BinarySearchTree() # An empty tree. Tests removal of single node. self.empty = BinarySearchTree() self.empty.add(self.houses[0], self.people[0]) self.empty.remove(self.houses[0]) # Tree with a single node, with highest key. self.root = BinarySearchTree() self.root.add(self.houses[-1], self.people[-1]) # Unbalanced tree: add the keys in ascending order. self.linear = BinarySearchTree() for house, person in zip(self.houses, self.people): self.linear.add(house, person) # Balanced tree: first add the median key. self.balanced = BinarySearchTree() self.balanced.add(33, 'Ann') self.balanced.add(34, 'Bob') self.balanced.add(35, 'John') self.balanced.add(32, 'John') self.balanced.add(31, 'Jane')
def testMin(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d) expected = min(l) self.assertEqual(expected, tree.min())
def testbstClone(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) clone = bst.bstClone() self.assertTrue(bst.sameTree(clone))
def testPreOrder(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d) for v in tree.preOrder(): pass
def testInorderSuccessor(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) self.assertEqual(bst.right.inOrderSuccessor().data, bst.right.right.left.data) self.assertEqual(bst.left.inOrderSuccessor().data, bst.left.right.left.data) self.assertEqual(bst.right.right.inOrderSuccessor().data, bst.right.right.right.data)
def testCommonAncestor(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) self.assertEqual(bst.commonAncestor(4, 12), 8) self.assertEqual(bst.commonAncestor(4, 10), 8) self.assertEqual(bst.commonAncestor(4, 14), 8) self.assertEqual(bst.commonAncestor(1, 15), 8)
def testInOrder(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d) gen = tree.inOrder() l.sort() # inOrder gives the elements in sorted Order always in BinaryTree for i in l: self.assertEqual(i, gen.next())
def testWellOrderedNess(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) self.assertTrue(bst.wellOrdered()) bst.left.data = 300 self.assertFalse(bst.wellOrdered())
def testSearchForData(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d) for i in l: self.assertTrue(tree.search(i)) self.assertFalse(tree.search(-1))
def testCreateBSTFromTwoTraversals(self): inOrder = [1, 2, 3, 4, 5, 6 ,7 ,8 ,9, 10, 11, 12, 13, 14, 15] preOrder = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] bstFromTraversals = BinarySearchTree.createBSTFromTwoTraversals(inOrder, preOrder, 0, len(inOrder)-1) bst = BinarySearchTree() l = [8, 12, 4, 14, 2, 6, 10, 9, 7, 5, 11, 13, 3, 1, 15] for v in l: bst.insert(v) self.assertTrue(bst.sameTree(bstFromTraversals))
def testBreadthFirstTraversal(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) expectedBFSOrder = [8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15] gen = bst.bfsTraversal() for expectedValue in expectedBFSOrder: self.assertEqual(expectedValue, gen.next())
def testCountTrees(self): #Assumes only Binary Tree, doesn't have to be a BST self.assertEqual(BinarySearchTree.countTrees(0), 1) self.assertEqual(BinarySearchTree.countTrees(1), 1) self.assertEqual(BinarySearchTree.countTrees(2), 2) self.assertEqual(BinarySearchTree.countTrees(3), 5) self.assertEqual(BinarySearchTree.countTrees(4), 14) self.assertEqual(BinarySearchTree.countTrees(6), 132) self.assertEqual(BinarySearchTree.countTrees(7), 429) self.assertEqual(BinarySearchTree.countTrees(10), BinarySearchTree.catalan(10))
def testSum(self): l = [-15, 5, 6, -8, 1, 3, 9, 2, 6, None, None, None, None, 4, 0, None, None, None, None, None, None, None, -1, 10, None] s = 0 for v in l: if v: s += v bt = BinaryTree() bt.create(l) self.assertEqual(bt.sum(), s) bstTwo = BinarySearchTree() l = [8, 2, 1, 4, 5, 3, 9, 10, 15, 13, 12, 14, 18] for v in l: bstTwo.insert(v) self.assertEqual(bstTwo.sum(), sum(l))
def testSpaceEfficientTraversal(self): bstOne = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bstOne.insert(d) bstTwo = bstOne clone = bstOne genOne = bstTwo.spaceEfficientTraversal() genTwo = bstOne.inOrder() l.sort() # inOrder gives the elements in sorted Order always in BinaryTree for i in l: self.assertEqual(i, genOne.next()) self.assertEqual(i, genTwo.next()) #create a copyTree method in the API and use it to test the similarity[Deep Copy] self.assertTrue(bstOne.sameTree(clone))
def test_can_create_complex_tree(self): expected = TreeNode( "4", TreeNode("2", TreeNode("1", None, None), TreeNode("3", None, None)), TreeNode("6", TreeNode("5", None, None), TreeNode("7", None, None)), ) self.assertTreeEqual( BinarySearchTree(["4", "2", "6", "1", "3", "5", "7"]).data(), expected)
def testDepth(self): tree = BinarySearchTree() l = range(100) for d in l: tree.insert(d) self.assertEqual(tree.getDepth(), len(l)) tree1 = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree1.insert(d) self.assertEqual(tree1.getDepth(), 4)
def testIsBST(self): bstOne = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bstOne.insert(d) self.assertTrue(bstOne.isBST()) bstTwo = BinarySearchTree() l = range(100) for d in l: bstTwo.insert(d) self.assertTrue(bstTwo.isBST())
def printTreeToList(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) blist = bst.treeToList() bst.printList(blist)
def testHasPathSum(self): tree = BinarySearchTree() l = range(100) s = 0 for d in l: tree.insert(d) s += d self.assertTrue(tree.hasPathSum(s)) tree1 = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree1.insert(d) expected_sums = [8, 12, 14, 15, 17, 18, 23, 25, 20, 30, 34, 39, 41, 47, 49] for e in expected_sums: self.assertTrue(tree1.hasPathSum(e))
def testMirror(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d) tree.mirror() # when you do a mirror of a BST, the inOrder gives you elements in descending order l.sort(reverse=True) inOrderGen = tree.inOrder() for v in l: self.assertEqual(v, inOrderGen.next())
def testDelete(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d) # delete elements one by one and verify that it doesn't exist deleted = [] for x in l: deleted.append(x) tree = tree.delete(x) #verfiy all other elements exist checks = [d for d in l if d not in deleted] for v in checks: self.assertTrue(tree and tree.search(v)) #verify x doesn't exist self.assertFalse(tree and tree.search(x))
def test_can_sort_single_number(self): expected = ["2"] assert BinarySearchTree(["2"]).sorted_data() == expected
def testSameTree(self): treeOne = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: treeOne.insert(d) treeTwo = BinarySearchTree() for d in l: treeTwo.insert(d) self.assertTrue(treeOne.sameTree(treeTwo)) self.assertTrue(treeTwo.sameTree(treeOne)) treeTwo.insert(100) self.assertFalse(treeTwo.sameTree(treeOne)) treeOne.insert(100) self.assertTrue(treeTwo.sameTree(treeOne))
def test_greater_number_at_right_node(self): expected = TreeNode("4", None, TreeNode("5", None, None)) self.assertTreeEqual(BinarySearchTree(["4", "5"]).data(), expected)
def test_same_number_at_left_node(self): expected = TreeNode("4", TreeNode("4", None, None), None) self.assertTreeEqual(BinarySearchTree(["4", "4"]).data(), expected)
def test_smaller_number_at_left_node(self): expected = TreeNode("4", TreeNode("3", None, None), None) bst = BinarySearchTree(["4", "3"]) self.assertTreeEqual(bst.data(), expected)
def testGetLeafCount(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) self.assertEqual(bst.getLeafCount(), 8) bst = BinarySearchTree() bst.insert(2) bst.insert(1) self.assertEqual(bst.getLeafCount(), 1) bst.insert(3) self.assertEqual(bst.getLeafCount(), 2)
class TestBST(unittest.TestCase): def setUp(self): # The keys are unique house numbers in a street. # The values are the names of inhabitants. self.houses = [number for number in range(31, 36)] self.people = ['Jane', 'John', 'Ann', 'Bob', 'John'] # Create trees for the tests to use. # A brand new tree. self.new = BinarySearchTree() # An empty tree. Tests removal of single node. self.empty = BinarySearchTree() self.empty.add(self.houses[0], self.people[0]) self.empty.remove(self.houses[0]) # Tree with a single node, with highest key. self.root = BinarySearchTree() self.root.add(self.houses[-1], self.people[-1]) # Unbalanced tree: add the keys in ascending order. self.linear = BinarySearchTree() for house, person in zip(self.houses, self.people): self.linear.add(house, person) # Balanced tree: first add the median key. self.balanced = BinarySearchTree() self.balanced.add(33, 'Ann') self.balanced.add(34, 'Bob') self.balanced.add(35, 'John') self.balanced.add(32, 'John') self.balanced.add(31, 'Jane') def test_is_empty(self): self.assertTrue(self.new.is_empty()) self.assertTrue(self.empty.is_empty()) self.assertFalse(self.root.is_empty()) self.assertFalse(self.linear.is_empty()) self.assertFalse(self.balanced.is_empty()) def test_height(self): self.assertEqual(self.new.height(), -1) self.assertEqual(self.empty.height(), -1) self.assertEqual(self.root.height(), 0) self.assertEqual(self.linear.height(), 4) self.assertEqual(self.balanced.height(), 2) def test_smallest_key(self): self.assertEqual(self.new.smallest_key(), None) self.assertEqual(self.empty.smallest_key(), None) self.assertEqual(self.root.smallest_key(), self.houses[-1]) self.assertEqual(self.linear.smallest_key(), self.houses[0]) self.assertEqual(self.balanced.smallest_key(), self.houses[0]) def test_in_order(self): self.assertEqual(self.new.in_order(), []) self.assertEqual(self.empty.in_order(), []) self.assertEqual(self.root.in_order(), [self.houses[-1]]) self.assertEqual(self.linear.in_order(), self.houses) self.assertEqual(self.balanced.in_order(), self.houses) def test_post_order(self): self.assertEqual(self.new.post_order(), []) self.assertEqual(self.empty.post_order(), []) self.assertEqual(self.root.post_order(), [self.houses[-1]]) self.assertEqual(self.linear.post_order(), [35, 34, 33, 32, 31]) self.assertEqual(self.balanced.post_order(), [31, 32, 35, 34, 33]) def test_value(self): for key, value in zip(self.houses, self.people): self.assertEqual(self.new.value(key), None) self.assertEqual(self.empty.value(key), None) if key == self.houses[-1]: self.assertEqual(self.root.value(key), value) else: self.assertEqual(self.root.value(key), None) self.assertEqual(self.linear.value(key), value) self.assertEqual(self.balanced.value(key), value) def test_value_change(self): # The previous tests with setUp already test adding new nodes. # This test checks the change of value for an existing key. # Swap the values of the lowest and highest keys. self.people[0], self.people[-1] = self.people[-1], self.people[0] # Update the affected trees. self.root.add(self.houses[-1], self.people[-1]) self.linear.add(self.houses[0], self.people[0]) self.linear.add(self.houses[-1], self.people[-1]) self.balanced.add(self.houses[0], self.people[0]) self.balanced.add(self.houses[-1], self.people[-1]) # Test retrieval of the new values. self.test_value() def test_remove_and_contains(self): # Get the middle key: it's the root of the balanced tree, # and doesn't exist in the single-node tree. index = len(self.houses) // 2 key = self.houses[index] # Remove it from each tree and confirm it's not found anymore. # This also tests that removing an unknown key doesn't change a tree. self.new.remove(key) self.assertFalse(key in self.new) self.empty.remove(key) self.assertFalse(key in self.empty) self.root.remove(key) self.assertFalse(key in self.root) self.linear.remove(key) self.assertFalse(key in self.linear) self.balanced.remove(key) self.assertFalse(key in self.balanced) # Remove from the inputs. Test retrieval for the other keys. self.houses.pop(index) self.people.pop(index) self.test_value()
def testGetInternalNodesCount(self): bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d)
def testCountNoOfNodes(self): tree = BinarySearchTree() l = range(100) for d in l: tree.insert(d) self.assertEqual(tree.size(), len(l))
def test_can_sort_if_second_number_is_same_as_first(self): expected = ["2", "2"] assert BinarySearchTree(["2", "2"]).sorted_data() == expected
def testPostOrder(self): tree = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: tree.insert(d)
def test_data_is_retained(self): expected = TreeNode("4", None, None) bst = BinarySearchTree(["4"]) self.assertTreeEqual(bst.data(), expected)
def test_can_sort_if_second_number_is_greater_than_first(self): expected = ["2", "3"] assert BinarySearchTree(["2", "3"]).sorted_data() == expected
def testDiameter(self): bstOne = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bstOne.insert(d) self.assertEqual(bstOne.diameter(), 7) # single node b = BinarySearchTree() b.insert(8) self.assertEqual(b.diameter(), 1) b.insert(4) self.assertEqual(b.diameter(), 2) bstTwo = BinarySearchTree() l = [8, 2, 1, 4, 5, 3, 9, 10, 15, 13, 12, 14, 18] for v in l: bstTwo.insert(v) self.assertEqual(bstTwo.diameter(), 9)
def test_can_sort_complex_tree(self): expected = ["1", "2", "3", "5", "6", "7"] assert BinarySearchTree(["2", "1", "3", "6", "7", "5"]).sorted_data() == expected
def testRadius(self): """ Given a binary tree find all the nodes at k distance from a given node. """ bst = BinarySearchTree() l = [8, 4, 2, 1, 3, 6, 5, 7, 12, 10, 9, 11, 14, 13, 15] for d in l: bst.insert(d) k2list = [2, 6, 10, 14] k3list = [1, 3, 5, 7, 9, 11, 13, 15] k2gen = bst.getRadiusList(2) for v in k2gen: self.assertTrue(v in k2list) k3gen = bst.getRadiusList(3) for v in k3gen: self.assertTrue(v in k3list) k1gen = bst.getRadiusList(1) for v in k1gen: self.assertTrue(v in [4, 12]) k0gen = bst.getRadiusList(0) for v in k0gen: self.assertTrue(v in [8]) # try with different tree structure """ 8 -----------------> radius 0 =>[8] / \ 2 9 -----------------> radius 1 =>[2, 9] / \ \ 1 4 10 -----------------> radius 2 =>[1, 4, 10] / \ \ 3 5 15 -----------------> radius 3 =>[3, 5, 15] / \ 13 18 -----------------> radius 1 =>[13, 18] / \ 12 14 -----------------> radius 1 =>[12, 14] """ bstTwo = BinarySearchTree() l = [8, 2, 1, 4, 5, 3, 9, 10, 15, 13, 12, 14, 18] for v in l: bstTwo.insert(v) k3gen = bstTwo.getRadiusList(3) k3list = [3, 5, 15] for v in k3gen: self.assertTrue(v in k3list) k4gen = bstTwo.getRadiusList(4) k4list = [13, 18] for v in k4gen: self.assertTrue(v in k4list) k5gen = bstTwo.getRadiusList(5) k5list = [12, 14] for v in k5gen: self.assertTrue(v in k5list)