def test_size(self):
        # Size starts at 0
        self.assertEqual(self.fixture.size(), 0)
        # Doing a put increases the size to 1
        self.fixture.put("one", 1)
        self.assertEqual(self.fixture.size(), 1)
        # Putting a key that is already in doesn't change size
        self.fixture.put("one", 1)
        self.assertEqual(self.fixture.size(), 1)
        self.fixture.put("one", 2)
        self.assertEqual(self.fixture.size(), 1)

        self.fixture = BinarySearchTree()
        size = 0
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
            size += 1
            self.assertEqual(self.fixture.size(), size)

        shuffled = self.shuffle_list(self.key_val[:])
        self.fixture = BinarySearchTree()
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.size(), size)
    def test_delete_max(self):
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
        for i in range(self.fixture.size() - 1, 0, -1):
            self.fixture.delete_max()
            self.assertEqual(self.fixture.max_key(), self.key_val[i - 1][0])
        self.fixture.delete_max()
        self.assertEqual(self.fixture.max_key(), None)

        self.fixture = BinarySearchTree()
        shuffled = self.shuffle_list(self.key_val[:])
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
        for i in range(self.fixture.size() - 1, 0, -1):
            self.fixture.delete_max()
            self.assertEqual(self.fixture.max_key(), self.key_val[i - 1][0])
        self.fixture.delete_max()
        self.assertEqual(self.fixture.max_key(), None)
    def test_rank(self):
        self.assertEqual(self.fixture.rank("a"), None)
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.rank("a"), 0)
        self.assertEqual(self.fixture.rank("b"), 1)
        self.assertEqual(self.fixture.rank("c"), 2)
        self.assertEqual(self.fixture.rank("d"), 3)

        self.fixture = BinarySearchTree()
        shuffled = self.shuffle_list(self.key_val[:])
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.rank("a"), 0)
        self.assertEqual(self.fixture.rank("b"), 1)
        self.assertEqual(self.fixture.rank("c"), 2)
        self.assertEqual(self.fixture.rank("d"), 3)
    def test_put(self):
        # When BST is empty first put becomes root
        self.fixture.put("bbb", 1)
        self.assertEqual(self.fixture.root.key, "bbb")
        self.assertEqual(self.fixture.root.left, None)

        # Adding a key greater than root doesn't update the left tree
        # but does update the right
        self.fixture.put("ccc", 2)
        self.assertEqual(self.fixture.root.key, "bbb")
        self.assertEqual(self.fixture.root.left, None)
        self.assertEqual(self.fixture.root.right.key, "ccc")

        self.fixture = BinarySearchTree()
        self.fixture.put("bbb", 1)
        # Adding a key less than root doesn't update the right tree
        # but does update the left
        self.fixture.put("aaa", 2)
        self.assertEqual(self.fixture.root.key, "bbb")
        self.assertEqual(self.fixture.root.right, None)
        self.assertEqual(self.fixture.root.left.key, "aaa")

        self.fixture = BinarySearchTree()
        size = 0
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
            size += 1
            self.assertEqual(self.fixture.get(k), v)
            self.assertEqual(self.fixture.size(), size)

        shuffled = self.shuffle_list(self.key_val[:])
        self.fixture = BinarySearchTree()
        size = 0
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
            size += 1
            self.assertEqual(self.fixture.get(k), v)
            self.assertEqual(self.fixture.size(), size)
 def setUp(self):
     self.fixture = BinarySearchTree()
class TestBinarySearchTree(unittest.TestCase):
    key_val = [("a", 1), ("b", 2), ("c", 3), ("d", 4), ("e", 5), ("f", 6),
               ("g", 7), ("h", 8), ("i", 9)]

    key_val2 = [("d", 4), ("e", 5), ("f", 6), ("a", 1), ("b", 2), ("c", 3),
                ("g", 7), ("h", 8), ("i", 9)]

    balanced = [("d", 4), ("f", 6), ("e", 5), ("b", 2), ("a", 1), ("c", 3),
                ("g", 7)]

    def setUp(self):
        self.fixture = BinarySearchTree()

    def shuffle_list(self, ls):
        shuffle(ls)
        return ls

    def test_size(self):
        # Size starts at 0
        self.assertEqual(self.fixture.size(), 0)
        # Doing a put increases the size to 1
        self.fixture.put("one", 1)
        self.assertEqual(self.fixture.size(), 1)
        # Putting a key that is already in doesn't change size
        self.fixture.put("one", 1)
        self.assertEqual(self.fixture.size(), 1)
        self.fixture.put("one", 2)
        self.assertEqual(self.fixture.size(), 1)

        self.fixture = BinarySearchTree()
        size = 0
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
            size += 1
            self.assertEqual(self.fixture.size(), size)

        shuffled = self.shuffle_list(self.key_val[:])
        self.fixture = BinarySearchTree()
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.size(), size)

    def test_LCA(self):
        for pair in self.key_val2:
            k, v = pair
            self.fixture.put(k, v)
        self.assertEquals(4, self.fixture.LCA(self.fixture.root, 1, 9).val)

    def test_first_common_ancestor(self):
        input = [1, 2, 3, 4, 5, 6, 7, 8]
        root = self.fixture.create_minimal_bst_tree(input, 0, len(input) - 1)
        self.assertEqual(
            2,
            self.fixture.first_common_ancestor(root, root.left.left,
                                               root.left.right))

    def test_flip_equilvalent(self):
        #[0,3,1,None,None,None,2]
        root = tn(0)
        root.left = tn(3)
        root.right = tn(1)
        root.right.right = tn(2)

        #[0,3,1,2]
        root1 = tn(0)
        root1.left = tn(3)
        root1.right = tn(1)
        root1.left.left = tn(2)
        self.assertTrue(self.fixture.flipEquiv(root, root1))

    def is_balanced_bf(self):
        for pair in self.balanced:
            k, v = pair
            self.fixture.put(k, v)
        self.assertTrue(self.fixture.is_balanced_bf(self.fixture.root))

    def test_is_not_balanced_bf(self):
        for pair in self.key_val2:
            k, v = pair
            self.fixture.put(k, v)
        self.assertFalse(self.fixture.is_balanced_bf(self.fixture.root))

    def test_is_balanced(self):
        for pair in self.balanced:
            k, v = pair
            self.fixture.put(k, v)
        self.assertEquals(True,
                          self.fixture.is_balanced(self.fixture.root).balanced)

    def test_is_not_balanced(self):
        for pair in self.key_val2:
            k, v = pair
            self.fixture.put(k, v)
        self.assertEquals(False,
                          self.fixture.is_balanced(self.fixture.root).balanced)

    def test_is_empty(self):
        self.assertTrue(self.fixture.is_empty())
        self.fixture.put("a", 1)
        self.assertFalse(self.fixture.is_empty())

    def test_get(self):
        # Getting a key not in BST returns None
        self.assertEqual(self.fixture.get("one"), None)

        # Get with a present key returns proper value
        self.fixture.put("one", 1)
        self.assertEqual(self.fixture.get("one"), 1)

        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
            self.assertEqual(self.fixture.get(k), v)

        shuffled = self.shuffle_list(self.key_val[:])

        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
            self.assertEqual(self.fixture.get(k), v)

    def test_contains(self):
        self.assertFalse(self.fixture.contains("a"))
        self.fixture.put("a", 1)
        self.assertTrue(self.fixture.contains("a"))

    def test_put(self):
        # When BST is empty first put becomes root
        self.fixture.put("bbb", 1)
        self.assertEqual(self.fixture.root.key, "bbb")
        self.assertEqual(self.fixture.root.left, None)

        # Adding a key greater than root doesn't update the left tree
        # but does update the right
        self.fixture.put("ccc", 2)
        self.assertEqual(self.fixture.root.key, "bbb")
        self.assertEqual(self.fixture.root.left, None)
        self.assertEqual(self.fixture.root.right.key, "ccc")

        self.fixture = BinarySearchTree()
        self.fixture.put("bbb", 1)
        # Adding a key less than root doesn't update the right tree
        # but does update the left
        self.fixture.put("aaa", 2)
        self.assertEqual(self.fixture.root.key, "bbb")
        self.assertEqual(self.fixture.root.right, None)
        self.assertEqual(self.fixture.root.left.key, "aaa")

        self.fixture = BinarySearchTree()
        size = 0
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
            size += 1
            self.assertEqual(self.fixture.get(k), v)
            self.assertEqual(self.fixture.size(), size)

        shuffled = self.shuffle_list(self.key_val[:])
        self.fixture = BinarySearchTree()
        size = 0
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
            size += 1
            self.assertEqual(self.fixture.get(k), v)
            self.assertEqual(self.fixture.size(), size)

    def test_min_key(self):
        for pair in self.key_val[::-1]:
            k, v = pair
            self.fixture.put(k, v)
            self.assertEqual(self.fixture.min_key(), k)

        shuffled = self.shuffle_list(self.key_val[:])

        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
        self.assertEqual(self.fixture.min_key(), "a")

    def test_max_key(self):
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
            self.assertEqual(self.fixture.max_key(), k)

        shuffled = self.shuffle_list(self.key_val[:])

        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
        self.assertEqual(self.fixture.max_key(), "i")

    def test_floor_key(self):
        self.assertEqual(self.fixture.floor_key("a"), None)
        self.fixture.put("a", 1)
        self.fixture.put("c", 3)
        self.fixture.put("e", 5)
        self.fixture.put("g", 7)
        self.assertEqual(self.fixture.floor_key("a"), "a")
        self.assertEqual(self.fixture.floor_key("b"), "a")
        self.assertEqual(self.fixture.floor_key("g"), "g")
        self.assertEqual(self.fixture.floor_key("h"), "g")

        self.fixture.put("c", 3)
        self.fixture.put("e", 5)
        self.fixture.put("a", 1)
        self.fixture.put("g", 7)
        self.assertEqual(self.fixture.floor_key("a"), "a")
        self.assertEqual(self.fixture.floor_key("b"), "a")
        self.assertEqual(self.fixture.floor_key("g"), "g")
        self.assertEqual(self.fixture.floor_key("h"), "g")

    def test_ceiling_key(self):
        self.assertEqual(self.fixture.ceiling_key("a"), None)
        self.fixture.put("a", 1)
        self.fixture.put("c", 3)
        self.fixture.put("e", 5)
        self.fixture.put("g", 7)
        self.assertEqual(self.fixture.ceiling_key("a"), "a")
        self.assertEqual(self.fixture.ceiling_key("b"), "c")
        self.assertEqual(self.fixture.ceiling_key("g"), "g")
        self.assertEqual(self.fixture.ceiling_key("f"), "g")

        self.fixture.put("c", 3)
        self.fixture.put("e", 5)
        self.fixture.put("a", 1)
        self.fixture.put("g", 7)
        self.assertEqual(self.fixture.ceiling_key("a"), "a")
        self.assertEqual(self.fixture.ceiling_key("b"), "c")
        self.assertEqual(self.fixture.ceiling_key("g"), "g")
        self.assertEqual(self.fixture.ceiling_key("f"), "g")

    def test_select_key(self):
        shuffled = self.shuffle_list(self.key_val[:])
        self.assertEqual(self.fixture.select_key(0), None)
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
        self.assertEqual(self.fixture.select_key(0), "a")
        self.assertEqual(self.fixture.select_key(1), "b")
        self.assertEqual(self.fixture.select_key(2), "c")

    def test_rank(self):
        self.assertEqual(self.fixture.rank("a"), None)
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.rank("a"), 0)
        self.assertEqual(self.fixture.rank("b"), 1)
        self.assertEqual(self.fixture.rank("c"), 2)
        self.assertEqual(self.fixture.rank("d"), 3)

        self.fixture = BinarySearchTree()
        shuffled = self.shuffle_list(self.key_val[:])
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.rank("a"), 0)
        self.assertEqual(self.fixture.rank("b"), 1)
        self.assertEqual(self.fixture.rank("c"), 2)
        self.assertEqual(self.fixture.rank("d"), 3)

    def test_delete_min(self):
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
        for i in range(self.fixture.size() - 1):
            self.fixture.delete_min()
            self.assertEqual(self.fixture.min_key(), self.key_val[i + 1][0])
        self.fixture.delete_min()
        self.assertEqual(self.fixture.min_key(), None)

        self.fixture = BinarySearchTree()
        shuffled = self.shuffle_list(self.key_val[:])
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
        for i in range(self.fixture.size() - 1):
            self.fixture.delete_min()
            self.assertEqual(self.fixture.min_key(), self.key_val[i + 1][0])
        self.fixture.delete_min()
        self.assertEqual(self.fixture.min_key(), None)

    def test_delete_max(self):
        for pair in self.key_val:
            k, v = pair
            self.fixture.put(k, v)
        for i in range(self.fixture.size() - 1, 0, -1):
            self.fixture.delete_max()
            self.assertEqual(self.fixture.max_key(), self.key_val[i - 1][0])
        self.fixture.delete_max()
        self.assertEqual(self.fixture.max_key(), None)

        self.fixture = BinarySearchTree()
        shuffled = self.shuffle_list(self.key_val[:])
        for pair in shuffled:
            k, v = pair
            self.fixture.put(k, v)
        for i in range(self.fixture.size() - 1, 0, -1):
            self.fixture.delete_max()
            self.assertEqual(self.fixture.max_key(), self.key_val[i - 1][0])
        self.fixture.delete_max()
        self.assertEqual(self.fixture.max_key(), None)

    def test_delete(self):
        # delete key from an empty bst
        self.fixture.delete("a")
        self.assertEqual(self.fixture.root, None)
        self.assertEqual(self.fixture.size(), 0)
        # delete key not present in bst
        self.fixture.put("a", 1)
        self.fixture.delete("b")
        self.assertEqual(self.fixture.root.key, "a")
        self.assertEqual(self.fixture.size(), 1)
        # delete key when bst only contains one key
        self.fixture.delete("a")
        self.assertEqual(self.fixture.root, None)
        self.assertEqual(self.fixture.size(), 0)
        # delete parent key when it only has a left child
        self.fixture.put("b", 2)
        self.fixture.put("a", 1)
        self.assertEqual(self.fixture.root.left.key, "a")
        self.fixture.delete("b")
        self.assertEqual(self.fixture.root.key, "a")
        self.assertEqual(self.fixture.size(), 1)
        # delete parent key when it only has a right child
        self.fixture.put("b", 2)
        self.assertEqual(self.fixture.root.right.key, "b")
        self.fixture.delete("a")
        self.assertEqual(self.fixture.root.key, "b")
        self.assertEqual(self.fixture.size(), 1)
        # delete left child key
        self.fixture.put("a", 1)
        self.assertEqual(self.fixture.root.left.key, "a")
        self.fixture.delete("a")
        self.assertEqual(self.fixture.root.key, "b")
        self.assertEqual(self.fixture.size(), 1)
        # delete right child key
        self.fixture.put("a", 1)
        self.fixture.put("c", 3)
        self.assertEqual(self.fixture.root.right.key, "c")
        self.fixture.delete("b")
        self.assertEqual(self.fixture.root.key, "c")
        self.assertEqual(self.fixture.size(), 2)

        self.fixture.put("b", 2)
        self.fixture.delete("b")
        self.assertEqual(self.fixture.root.key, "c")
        self.assertEqual(self.fixture.size(), 2)

    def test_keys(self):
        self.assertEqual(self.fixture.keys(), [])

        for pair in self.key_val2:
            k, v = pair
            self.fixture.put(k, v)

        self.assertEqual(self.fixture.keys(),
                         ["a", "b", "c", "d", "e", "f", "g", "h", "i"])

    def test_create_minimal_bst_tree(self):
        input = [1, 2, 3, 4, 5, 6, 7, 8]

        actual = self.fixture.create_minimal_bst_tree(input, 0, len(input) - 1)
        self.assertEqual(2, actual.left.val)
        self.assertEqual(3, actual.left.right.val)
        self.assertEqual(None, self.fixture.bfs_with_level(None))
        (bfs, level) = self.fixture.bfs_with_level(actual)
        self.assertEqual([4, 2, 6, 1, 3, 5, 7, 8], bfs)
        self.assertEqual(4, level)

    def test_depth(self):
        input = [1, 2, 3, 4, 5, 6, 7, 8]
        tree = self.fixture.create_minimal_bst_tree(input, 0, len(input) - 1)
        self.assertEqual(0, self.fixture.level(None))
        self.assertEqual(1, self.fixture.level(tn(0, 1)))
        self.assertEqual(4, self.fixture.level(tree))

    def test_list_of_depths(self):
        array = [1, 2, 3, 4, 5, 6, 7, 8]
        input = self.fixture.create_minimal_bst_tree(array, 0, len(array) - 1)
        actual = self.fixture.list_of_depths(input)
        self.assertEqual([4],
                         self.fixture.list_of_depths(tn(0, 4))[0].getNodes(
                             list()))
        self.assertEqual([4], actual[0].head.getNodes(list()))
        self.assertEqual([2, 6], actual[1].head.getNodes(list()))
        self.assertEqual([1, 3, 5, 7], actual[2].head.getNodes(list()))
        self.assertEqual([8], actual[3].head.getNodes(list()))

    def test_is_not_bst(self):
        self.fixture.root = tn(0, 3)
        self.fixture.root.left = tn(0, 2)
        self.fixture.root.right = tn(0, 2)
        self.assertFalse(self.fixture.is_bst(self.fixture.root))

    def test_is_bst(self):
        input = [1, 2, 3, 4, 5, 6, 7, 8]
        self.fixture.create_minimal_bst_tree(input, 0, len(input) - 1)
        self.assertTrue(self.fixture.is_bst(self.fixture.root))