Binary Tree Data Structure



  • Unlike Arrays, Linked Lists, Stack and queues, which are linear data structures, trees are hierarchical data structures.


  • The topmost node is called root of the tree. The elements that are directly under an element are called its children. The element directly above something is called its parent.


  • Applications of Trees are :


    1. Manipulate hierarchical data.


    2. Trees provide moderate access/search (quicker than Linked List and slower than arrays)


    3. Trees provide moderate insertion/deletion (quicker than Arrays and slower than Unordered Linked Lists).


    4. Like Linked Lists and unlike Arrays, Trees don’t have an upper limit on number of nodes as nodes are linked using pointers.


  • Binary Tree Representation in C : A tree is represented by a pointer to the topmost node in tree. If the tree is empty, then value of root is NULL. A Tree node contains following parts.


    1. Data


    2. Pointer to left child


    3. Pointer to right child


    4. struct node 
      {
        int data;
        struct node *left;
        struct node *right;
      };
      



Properties of binary tree



  • The maximum number of nodes at level ‘n’ of a binary tree is 2n-1


  • Maximum number of nodes in a binary tree of height ‘h’ is 2h – 1.


  • In a Binary Tree with "N" nodes, minimum possible height or minimum number of levels is ⌈ Log2(N+1) ⌉


  • A Binary Tree with "L" leaves has at least ⌈ Log2L ⌉ + 1 levels.


  • In Binary tree, number of leaf nodes is always one more than nodes with two children.




Types of Binary Tree



  • Full Binary Tree : A Binary Tree is full if every node has 0 or 2 children. Following are examples of full binary tree. We can also say a full binary tree is a binary tree in which all nodes except leaves have two children. In a Full Binary, number of leaf nodes is number of internal nodes plus 1


  • Types of Binary Tree
  • Complete Binary Tree : A Binary Tree is complete Binary Tree if all levels are completely filled except possibly the last level and the last level has all keys as left as possible


  • Perfect Binary Tree : A Binary tree is Perfect Binary Tree in which all internal nodes have two children and all leaves are at same level. A Perfect Binary Tree of height h (where height is number of nodes on path from root to leaf) has 2h – 1 node.


  • A full binary tree (sometimes proper binary tree or 2-tree or strictly binary tree) : is a tree in which every node other than the leaves has two children. So you have no nodes with only 1 child. Appears to be the same as strict binary tree.


  • Types of Binary Tree
  • Balanced Binary Tree : A binary tree is balanced if height of the tree is O(Log n) where n is number of nodes. For Example, AVL tree maintain O(Log n) height by making sure that the difference between heights of left and right subtrees is 1. Red-Black trees maintain O(Log n) height by making sure that the number of Black nodes on every root to leaf paths are same and there are no adjacent red nodes. Balanced Binary Search trees are performance wise good as they provide O(log n) time for search, insert and delete.


  • A degenerate (or pathological) tree : A Tree where every internal node has one child. Such trees are performance-wise same as linked list.


  • Types of Binary Tree


Binary Search Tree



  • Binary Search Tree, is a node-based binary tree data structure which has the following properties :


    1. left child node is smaller than its parent Node i.e. The left subtree of a node contains only nodes with keys lesser than the node’s key


    2. right child node is greater than its parent Node i.e. The right subtree of a node contains only nodes with keys greater than the node’s key.


    3. The left and right subtree each must also be a binary search tree. There must be no duplicate nodes.


  • The above properties of Binary Search Tree provide an ordering among keys so that the operations like search, minimum and maximum can be done fast. If there is no ordering, then we may have to compare every key to search a given key.




Binary Search Tree




  1. The search binary tree data structure supports many dynamic-set operations, including SEARCH, MINIMUM, MAXIMUM, PREDECESSOR, SUCCESSOR, INSERT,and DELETE. Thus, we can use a search tree both as a dictionary and as a priority queue.


  2. Basic operations on a binary search tree take time proportional to the height of the tree. For a complete binary tree with n nodes, such operations run in Θ(lg n). If the tree is a linear chain of n nodes, however, the same operations take Θ(n) worst-case time.


  3. A tree by a linked data structure in which each node is an object. In addition to a key and satellite data, each node contains attributes left, right,and p that point to the nodes corresponding to its left child, right child and parent node respectively.


  4. If a child or the parent is missing, the appropriate attribute contains the value NIL. The root node is the only node in the tree whose parent is NIL.


  5. Binary search Tree property states that: Let x be a node in a binary search tree. If y is a node in the left subtree of x, then y.key ≤ x.key. If y is a node in the right subtree of x,then y.key ≥ x.key.


  6. binary search tree
  7. The binary-search-tree property allows us to print out all the keys in a binary search tree in sorted order by a simple recursive algorithm, called an inorder tree walk. This algorithm is so named because it prints the key of the root of a subtree between printing the values in its left subtree and printing those in its right subtree. (Similarly, a preorder tree walk prints the root before the values in either subtree, and a postorder tree walk prints the root after the values in its subtrees.)




Binary Search Tree - Operations



  1. INORDER-TREE-WALK(x)
  2. if x ≠ NIL
  3.     INORDER-TREE-WALK(x.left)
  4.     print(x.key)
  5.     INORDER-TREE-WALK(x.right)


If x is the root of an n-node subtree, then the call INORDER-TREE-WALK(x) takes Θ(n) time.


  1. TREE-SEARCH(x,k)
  2. if x ==NIL OR k == x.key
  3.     return x
  4. if k < x.key
  5.    return TREE-SEARCH(x.left,k)
  6. else return TREE-SEARCH(x.right,k)

Running time of TREE-SEARCH is O(h), where h is the height of the tree.


  1. TREE-Minimum(x)
  2. while x.left ≠ NIL
  3.     x = x.left
  4. return x



  1. TREE-Maximum(x)
  2. while x.right ≠ NIL
  3.     x = x.right
  4. return x

Running time of TREE-Minimum(x) and TREE-Minimum(x) is O(h), where h is the height of the tree.


  1. TREE-Successor(x)
  2. if x.right ≠ NIL
  3.     return TREE-Minimum(x.right)
  4. y = x.p
  5. while y ≠ NIL and x == y.right
  6.     x = y
  7.     y = y.p
  8. return y

Running time of TREE-Successor(x) and TREE-Predecessor(x) is O(h), where h is the height of the tree.



  1. TREE-INSERT(T,z)
  2. y = NIL
  3. x = T.root
  4. while x ≠ NIL
  5.    y = x
  6.    if z.key < x.key
  7.       x = x.left
  8.    else x = x.right
  9. z.p = y 
  10. if y == NIL 
  11.    T.root = z
  12. else if z.key < y.key 
  13.    y.left = z
  14. else y.right = z 

Like the other primitive operations on search trees, the procedure T REE-INSERT runs in O(h) time on a tree of height h.





Binary Search Tree - Deletion Operation



  1. If z (node to be deleted) has no children, then we simply remove it by modifying its parent to replace z with NIL as its child.


  2. If z has just one child, then we elevate that child to take z’s position in the tree by modifying z’s parent to replace z by z’s child.


  3. If z has two children, then we find z’s successor y — which must be in z’s right subtree - and have y take z’s position in the tree. The rest of z’s original right subtree becomes y’s new right subtree, and z’s left subtree becomes y’s new left subtree.


  4. binary search tree - deletion



  1. TREE-DELETE(T,z)
  2. if z.LEFT == NIL
  3.    TRANSPLANT(T,z,z.right)
  4. elseif z.RIGHT == NIL
  5.    TRANSPLANT(T,z,z.left)
  6. else y = TREE-MINIMUM.(z.right)
  7.    if y.p ≠ z
  8.       TRANSPLANT(T,y,y.right)
  9.       y.right = z.right
  10.       y.right.p = y
  11.    TRANSPLANT(T,z,y)
  12.    y.left = z.left
  13.    y.left.p = y


  1. TRANSPLANT(T,u,v)
  2. if u.p == NIL
  3.    T.root = v
  4. elseif u == u.p.left
  5.    u.p.left = v
  6. else u.p.right = v
  7. if v ≠ NIL
  8.    v.p = u.p


TREE-DELETE runs in O(h) time on a tree of height h.



Binary Tree Traversals - Inorder, Preorder, Postorder



  • Unlike linear data structures (Array, Linked List, Queues, Stacks, etc) which have only one logical way to traverse them, trees can be traversed in different ways. Following are the generally used ways for traversing trees.


  • Inorder Traversal : In case of binary search trees (BST), Inorder traversal gives nodes in non-decreasing order. To get nodes of BST in non-increasing order, a variation of Inorder traversal where Inorder traversal is reversed, can be used.


    1. Algorithm Inorder(tree)


    2. Traverse the left subtree, i.e., call Inorder(left-subtree)


    3. Visit the root.


    4. Traverse the right subtree, i.e., call Inorder(right-subtree)


  • Preorder traversal : Preorder traversal is used to create a copy of the tree. Preorder traversal is also used to get prefix expression on of an expression tree.


    1. Algorithm Preorder(tree)


    2. Visit the root.


    3. Traverse the left subtree, i.e., call Preorder(left-subtree)


    4. Traverse the right subtree, i.e., call Preorder(right-subtree)


  • Postorder traversal : Postorder traversal is used to delete the tree.


    1. Algorithm Postorder(tree)


    2. Traverse the left subtree, i.e., call Postorder(left-subtree)


    3. Traverse the right subtree, i.e., call Postorder(right-subtree)


    4. Visit the root.



Q. Perform Inorder, Preorder and Postorder traversal of a binary search tree


    Inorder, Preorder and Postorder traversal
  • Depth First Traversals :


    1. Inorder (Left, Root, Right) : 4 2 5 1 3


    2. Preorder (Root, Left, Right) : 1 2 4 5 3


    3. Postorder (Left, Right, Root) : 4 5 2 3 1


  • Breadth First or Level Order Traversal : 1 2 3 4 5