Trees

Trees: Introduction & Terminology

A node of a tree is a single element of a tree. A tree is a collection of nodes. A node of a binary tree has a value and two pointers: left and right. A node of a non-binary tree has a value and any number of pointers.

Full: A Full Binary Tree (FBT) is a tree in which every node other than the leaves has two children.

Perfect: A Perfect Binary Tree (PBT) is a tree with all leaf nodes at the same depth. All internal nodes have degree 2.

Complete: A Complete Binary Tree(CBT) is a binary tree in which every level, except possibly the last, is completely filled, and all nodes are as far left as possible.

Child: A child is a node that is a descendant of its parent.

Sibling: A sibling is a node that is a descendant of the same parent.

Leaf: A leaf is a node that has no children.

Binary Search Trees: Example

A binary search tree (BST) is a binary tree in which the value of each node is greater than the values in all of its left descendants and less than the values in all of its right descendants.

BST: Big O

The number of nodes in a binary tree with height h is O(2^h). Finding a node in a binary tree with height h is O(h). Therefore, the time complexity of a binary search tree is O(log n), where n is the number of nodes in the tree. The worst case is O(n) when the tree is completely unbalanced.

Comparison of the time complexity of a binary search tree with a linked list:

Insert(): O(1) in a linked list. In a binary search tree, Omega (best case) and Theta (average case) are both (log n). However, worst case is O(n) and Big O measures worst case.

Lookup(): O(n) in a linked list, O(log n) in a binary search tree.

Remove(): O(n) in a linked list, O(log n) in a binary search tree.

BST: Constructor

class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right = None

class BinarySearchTree:
    def __init__(self):
        self.root = None

my_tree = BinarySearchTree()

print(my_tree.root)

The above code creates a empty tree.

BST: Insert

    def insert(self, value):
        new_node = Node(value)
        if self.root is None:
            self.root = new_node
            return True
        temp = self.root
        while (True):
            if new_node.value == temp.value:
                return False
            if new_node.value < temp.value:
                if temp.left is None:
                    temp.left = new_node
                    return True
                temp = temp.left
            else: 
                if temp.right is None:
                    temp.right = new_node
                    return True
                temp = temp.right

my_tree = BinarySearchTree()
my_tree.insert(2)
my_tree.insert(1)
my_tree.insert(3)

BST: Contains

    def contains(self, value):
        temp = self.root
        while (temp is not None):
            if value < temp.value:
                temp = temp.left
            elif value > temp.value:
                temp = temp.right
            else:
                return True
        return False

my_tree = BinarySearchTree()
my_tree.insert(47)
my_tree.insert(21)
my_tree.insert(76)
my_tree.insert(18)
my_tree.insert(27)
my_tree.insert(52)
my_tree.insert(82)

print(my_tree.contains(27))

print(my_tree.contains(17))

BST: Minimum Value

    def min_value_node(self, current_node):
        while (current_node.left is not None):
            current_node = current_node.left
        return current_node

Last updated