Trees
Trees
In linear data structure, data is organized in sequential order and in non-linear data
structure, data is organized in random order. Tree is a very popular data structure used in
wide range of applications. A tree data structure can be defined as follows...
Tree is a non-linear data structure which organizes data in hierarchical structure and this is a
recursive definition. i.e it is a collection of data (Node) which is organized in hierarchical
structure.
In tree data structure, every individual element is called as Node. Node in a tree data
structure, stores the actual data of that particular element and link to next element in
hierarchical structure.
In a tree data structure, if we have N number of nodes then we can have a maximum of N-
1 number of links. All the nodes are connected.
Example
Terminology
Root: In a tree data structure, the first node is called as Root Node. Every tree must have root
node. We can say that root node is the origin of tree data structure. In any tree, there must be
only one root node. We never have multiple root nodes in a tree.
Edge: In a tree data structure, the connecting link between any two nodes is called as EDGE.
In a tree with 'N' number of nodes there will be a maximum of 'N-1' number of edges.
Parent: In a tree data structure, the node which is predecessor of any node is called
as PARENT NODE. In simple words, the node which has branch from it to any other node is
1
Trees
called as parent node. Parent node can also be defined as "The node which has child /
children". i.e The element directly above something is called its parent
Child:In a tree data structure, the node which is descendant of any node is called as CHILD
Node. In simple words, the node which has a link from its parent node is called as child node.
In a tree, any parent node can have any number of child nodes. In a tree, all the nodes except
root are child nodes. i.e The elements that are directly under an element are called its
children.
Siblings: In a tree data structure, nodes which belong to same Parent are called
as SIBLINGS. In simple words, the nodes with same parent are called as Sibling nodes.
Leaf: In a tree data structure, the node which does not have a child is called as LEAF Node.
In simple words, a leaf is a node with no child. In a tree data structure, the leaf nodes are also
called as External Nodes. External node is also a node with no child. In a tree, leaf node is
also called as 'Terminal' node.
Internal Nodes: In a tree data structure, the node which has atleast one child is called
as INTERNAL Node. In simple words, an internal node is a node with atleast one child.
2
Trees
In a tree data structure, nodes other than leaf nodes are called as Internal Nodes. The root
node is also said to be Internal Node if the tree has more than one node. Internal nodes are
also called as 'Non-Terminal' nodes.
Degree: In a tree data structure, the total number of children of a node is called
as DEGREE of that Node. In simple words, the Degree of a node is total number of children
it has. The highest degree of a node among all the nodes in a tree is called as 'Degree of Tree'
Level: In a tree data structure, the root node is said to be at Level 0 and the children of root
node are at Level 1 and the children of the nodes which are at Level 1 will be at Level 2 and
so on... In simple words, in a tree each step from top to bottom is called as a Level and the
Level count starts with '0' and incremented by one at each level (Step).
Height: In a tree data structure, the total number of nodes from leaf node to a particular node
in the longest path is called as HEIGHT of that Node. In a tree, height of the root node+1 is
said to be height of the tree. In a tree, height of all leaf nodes is '0'.
Depth: In a tree data structure, the total number of egdes from root node to a particular node
is called as DEPTH of that Node. In a tree, the total number of nodes from root node to a leaf
3
Trees
node in the longest path is said to be Depth of the tree. In simple words, the highest depth of
any leaf node+1 in a tree is said to be depth of that tree. In a tree, depth of the root node is '0'.
Path: In a tree data structure, the sequence of Nodes and Edges from one node to another
node is called as PATH between that two Nodes. Length of a Path is total number of nodes in
that path. In below example the path A - B - E - J has length 4.
Sub Tree: In a tree data structure, each child from a node forms a subtree recursively. Every
child node will form a subtree on its parent node.
Binary Tree
A binary tree is a finite set of nodes that is either empty or consist a root node and two
disjoint binary trees called the left subtree and the right subtree.
In a normal tree, every node can have any number of children. Binary tree is a special type of
tree data structure in which every node can have a maximum of 2 children. One is known as
left child and the other is known as right child.
A tree in which every node can have a maximum of two children is called as Binary Tree.
In a binary tree, every node can have either 0 children or 1 child or 2 children but not more
than 2 children.
4
Trees
Strictly Binary Tree:In a binary tree, every node can have a maximum of two children. But
in strictly binary tree, every node should have exactly two children or none. That means
every internal node must have exactly two children. A strictly Binary Tree can be defined as
follows...
A binary tree in which every node has either two or zero number of children is called Strictly
Binary Tree. It can also be called as Proper Binary Tree or 2-Tree.
A full Binary tree is a strictly binary tree.
5
Trees
A binary tree T is said to be complete binary tree if - All its levels, except possibly the last,
have the maximum number of nodes and All the nodes at the last level appears as far left as
possible.
Every Full binary tree is a complete binary tree but not every complete binary tree is full.
IF L is the level of complete binary tree then 2L – 1 nodes present in the tree.
Consider the following tree, which is complete binary tree:
In above figure, a normal binary tree is converted into complete binary tree by adding dummy
nodes which are in rectangle shape.
degenerate (or pathological) tree A Tree where every internal node has one child. Such
trees are performance-wise same as linked list.
10
/
20
\
30
\
40
6
Trees
A binary tree data structure is represented using two methods. Those methods are as
follows...
Array Representation
Linked List Representation
1. Array Representation
In array representation of binary tree, we use a one dimensional array (1-D Array) to
represent a binary tree.
Consider the above example of binary tree and it is represented as follows...
To represent a binary tree of height 'h' using array representation, we need one dimensional
array with a maximum size of 2h - 1.
If root node is placed at index 0:
A node is at location i
its left child is at 2i+1
right child is at location 2i+2
parent is at (i-1)/2
7
Trees
Struct treenode {
Int data;
Sturct treenode * left,*right;
}
The above example of binary tree represented using Linked list representation is shown as
follows...
8
Trees
Insertion: For inserting element , we have to traverse all elements. Therefore, insertion in
binary tree has worst case complexity of O(n).
In binary trees to insert node
Option 1: a new node before insert has to specify 1) whose child it is going to be mention
whether new node goes as left/right child.
To add a new node to leaf node, a new node should also mention whether new node goes as
left/right child.
In this first we have to search for parent node and then add new node as either left or right of
parent.
5 5
/ \ / \
4 6 After insertion 4 6
/ \ / / \ / \
8 9 7 8 9 10 6
Insert 10 as a child of 6
Here first we have to search for 6 and then insert 10 as right child of 6 if left is empty we can
insert it as left child.
insert(root,x)
{// x is the element to be inserted in to tree.
[Link] memory for new node temp;
2. if temp==NULL
9
Trees
Deletion: For deletion of element, we have to traverse all elements to find element to be
deleted. Therefore, deletion in binary tree has worst case complexity of O(n).
For deletion, only certain nodes in a binary tree can be removed unambiguously.
Deleting leaf node: Suppose that the node to delete is node A. If A has no children, deletion is
accomplished by setting the child of A's parent to null.
Node with single child:
If A has one child, set the parent of A's child to A's parent and set the child of A's parent to
A's child.
Node with two childs:
In a binary tree, a node with two children cannot be deleted unambiguously. Some support
this but entire tree has to be rebuilt.
Example : 5
/ \
4 6
/ \ /
8 9 10
Delete 6: put 5 right child as 10
5
/ \
4 10
/ \
8 9
Delete 8: put 4 left child as NULL
5
/ \
4 10
\
9
Delete 5: It is not possible.
10
Trees
Any of the traversal methods can be used, since each method visits each node exactly one
time.
Count Nodes(root)
{
Count=0
Create an empty queue.
Enqueue(root)
while (there are elements in the tree i.e queue not empty)
{
countt++
x=dequeue()
if (there is a left child. i.e x->left!=NULL)
enqueue(x->left)
if (there is a right child i.e x->right!=NULL)
enqueue(x->left)
}
Write “no of nodes count”;
}
Finding the height of a binary tree
The height of the left subtree is determined; then the height of the right subtree is determined.
During the "visit" step, the height of the tree is determined as:
11
Trees
x=dequeue()
if(x->left==NULL&&x->right==NULL)
countt++
if (there is a left child. i.e x->left!=NULL)
enqueue(x->left)
if (there is a right child i.e x->right!=NULL)
enqueue(x->left)
}
Write “no of leaf nodes count”;
}
The delete a binary tree, all of its nodes need to be deleted. This can be done by performing a
postorder traversal. During the "visit" step, the node is deleted. By doing this, the left subtree
will be deleted, then the right subtree, and finally the root.
delete ()
delete(root)
set root to null
A traversal is a process that visits all the nodes in the tree. Since a tree is a nonlinear data
structure, there is no unique traversal. We will consider several traversal algorithms
There are three different types of traversals, depending on the visiting position of node
PreOrder traversal - visit the parent first and then left and right children;
InOrder traversal - visit the left child, then the parent and the right child;
PostOrder traversal - visit left child, then the right child and then the parent;
12
Trees
Inorder(root)
{
if(root != null) {
Inorder(root->left);
Process(root->data);
Inorder(root->right);
}
}
Process(root->data);
preorder(root->left);
preorder(root->right);
}
}
3. Post - Order Traversal ( leftChild - rightChild - root )
In Post-Order traversal, the root node is visited after left child and right child. In this
traversal, left child node is visited first, then its right child and then its root node. This is
recursively performed until the right most node is visited.
In post order traversal the last visited node is root.
postorder(BSTNode root)
{
if(root != null) {
postorder(root->left);
postorder(root->right);
Process(root->data);
}
}
13
Trees
In-Order Traversal :I - D - J - B - F - A - G - K - C - H
Pre-Order Traversal: A-B-D-I-J-F-C-G-K-H
Post-Order Traversal :I - J - D - F - B - K - G - H - C - A
Construction of a binary tree from traversal sequences:
We can construct a tree by taking the traversal sequences.
Construction of binary tree from In order and post order
14
Trees
From the post-order, we know that last element is the root. We can find the root in in-order
array. Then we can identify the left and right sub-trees of the root from in-order array.
Using the length of left sub-tree, we can identify left and right sub-trees in post-order array.
Recursively, we can build up the tree.
15
Trees
16
Trees
X=4 write 4
Stack s->5 3
X=5 write 5
Stack ->3
X=3 write 3
Stack->NULL
Output is:1 2 4 5 3
InOrder:
1) Create an empty stack S.
2) Initialize current node as root. Curr=root
3) Push the current node to S and set current = current->left until current is NULL
While(curr!=NULL) push(curr) curr=curr->left
4) If current is NULL and stack is not empty then
a) Pop the top item from stack. X=pop()
b) Print the popped item, set current = popped_item->right
write x; curr=x->right
c) Go to step 3.
5) If current is NULL and stack is empty then we are done.
Let us consider the below tree for example
1
/ \
2 3
/ \
4 5
Step 3 Pushes the current node and set current = current->left until current is NULL
current -> 1
push 1: Stack S -> 1
current -> 2
push 2: Stack S -> 2, 1
current -> 4
push 4: Stack S -> 4, 2, 1
current = NULL
17
Trees
b) print "2"
c) current -> 5/*right of 2 */ and go to step 3
Post order:
Approach:
We have seen how we do inorder and preorder traversals without recursion using Stack,
But post order traversal will be different and slightly more complex than other two.
Reason is post order is non-tail recursive ( The statements execute after the recursive
call).
If you just observe here, postorder traversal is just reverse of preorder traversal (if we
traverse the right node first and then left node.)
So idea is follow the same technique as preorder traversal and instead of printing it push
it to the another Stack so that they will come out in reverse order (LIFO).
At the end just pop all the items from the second Stack and print it.
Pseudo Code:
1. Push root into Stack1 S1.
2. while(S1 is not empty)
1. Pop the node from S1 and push it into S2.
2. Push the left and right child nodes of popped node into S1.
3. End Loop
4. Pop out all the nodes from S2 and print it.
18
Trees
1
/ \
2 3
/ \
4 5
S1->1
S1 not empty
S1->3 2 S2->1
S1->2 S2 ->3 1
S1->5 4 S2->2 3 1
S1->4 S2->5 2 3 1
S1->NULL S2->4 5 2 3 1
While S2 not empty
4 5 2 3 1 Output;
Binary Search Tree
In a binary tree, every node can have maximum of two children but there is no order of nodes
based on their values. In binary tree, the elements are arranged as they arrive to the tree, from
top to bottom and left to right.
Any operation in binary tree takes O(n) time complexity.
To enhance the performance of binary tree, we use special type of binary tree known
as Binary Search Tree. Binary search tree mainly focus on the search operation in binary tree.
Binary search tree can be defined as follows...
Binary Search Tree is a binary tree in which every node contains only smaller values in its
left subtree and only larger values in its right subtree.
In a binary search tree, all the nodes in left subtree of any node contains smaller values and
all the nodes in right subtree of that contains larger values as shown in following figure...
The following tree is a Binary Search Tree. In this tree, left subtree of every node contains
nodes with smaller values and right subtree of every node contains larger values.
19
Trees
Every Binary Search Tree is a binary tree but all the Binary Trees need not to be binary
search trees.
if (key >root->data)
search(root->right, key);
else
search(root->left, key);
}
3
/ \
20
Trees
2 4
/ \
1 5
Search(3,5) search(3,0)
3==5 false 3==0 false
5<3 false 0<3 true search(2,0)
Search(4,5) 2==0 false
4==5 false 0<2 true search(1,0)
5<4 false 1==0 flase
search(5,5) 0<1 true search(NULL,0)
5==5 key found. Null key not
found
The above is the recursive search
The same can also be implemented without recursion.
Iterative_search(root,key)
{
Curr=root;
While(curr!=NULL)
{
If(curr->data==key) write “key found” return
Else if(key<curr->data) curr=curr->left;
Else curr=curr->right
}
Write “key not found”;
}
Insertion Operation in BST
In a binary search tree, the insertion operation is performed with O(log n) time complexity. In
binary search tree, new node is always inserted as a leaf node. The insertion operation is
performed as follows...
A new key is always inserted at leaf. We start searching a key from root till we hit a leaf
node. Once a leaf node is found, the new node is added as a child of the leaf node.
Check whether root node is present or not(tree available or not). If root is NULL,
create root node.
If the element to be inserted is less than the element present in the root node, traverse
the left sub-tree recursively until we reach T->left/T->right is NULL and place the new node
at T->left(key in new node < key in T)/T->right (key in new node > key in T).
21
Trees
If the element to be inserted is greater than the element present in root node, traverse
the right sub-tree recursively until we reach T->left/T->right is NULL and place the new
node at T->left/T->right.
Algorithm recursive_insert(ptr,x)
{
// initially ptr=root
If(ptr==NULL) root=createnode();
If(ptr->data=x) write “ element already existed so no insertion” return;
Else if(x<ptr->data) ptr->left=recursive_insert(ptr->left,x);
Else ptr->rightt=recursive_insert(ptr->rightt,x);
}
Createnode()
{
Allocate memory for new node let it be temp;
If(temp==NULL) write”out of memory”; return
Temp->data=x;
Temp->left=temp->right=NULL
Return temp;
}
Algorithm insert(root,x)
{// x is the element to be inserted int the tree whose root is given
Allocate memory for new node let it be temp;
If(temp==NULL) write”out of memory”; return
Temp->data=x;
Temp->left=temp->right=NULL
Curr=root;
While(curr!=NULL)
{
Parent=curr;
If(x<curr->data) {
Curr=curr->left;
If(curr->left==NULL)
Parent->left=temp; return;
}
Else
If(x>curr->data) {
Curr=curr->right;
If(curr->rightt==NULL)
Parent->right=temp; return;
}
Else wrte” insertion not possible” return’
}
}
Example:
Insert 20 into the Binary Search Tree.
Tree is not available. So, create root node and place 10 into it.
22
Trees
20
Insert 23 into the given Binary Search Tree. 23 > 20 (data in root). So, 23 needs to be
inserted in the right sub-tree of 20.
20
\
23
Insert 13 into the given Binary Search Tree. 13 < 20(data in root). So, 13 needs to be
inserted in left sub-tree of 20.
20
/ \
13 23
20
/ \
13 23
/
9
Inserting 14.
20
/ \
13 23
/ \
9 14
Inserting 19.
20
/ \
13 23
/ \
9 14
\
19
Inserting 21.
20
/ \
13 23
/ \ /
9 14 21
\
19
23
Trees
Inserting 27.
20
/ \
13 23
/ \ / \
9 14 21 27
\
19
Inserting 24.
20
/ \
13 23
/ \ / \
9 14 21 27
\ /
19 24
2) Node to be deleted has only one child: Copy the child to the node and delete the child
50 50
/ \ delete(30) / \
30 70 ---------> 40 70
\ / \ / \
40 60 80 60 80
3. Node to be deleted has two children: Find maximum in the left sub tree replace node with
maximum element in the left or minimum element in the right subtree and delete that max or
min node.
24
Trees
50 60
/ \ delete(50) / \
40 70 ---------> 40 70
/ \ \
60 80 80
The important thing to note is, inorder successor is needed only when right child is not
empty. In this particular case, inorder successor can be obtained by finding the minimum
value in right child of the node.
DeleteNode(ptr,x)
{
curr=ptr;
parent=NULL
While(curr!=NULL)
{If(x<curr->data) { parent=curr; curr=curr->left; }
Else if(x>curr->data) { parent=curr;curr=curr->right;}
Else { //element founded
// for case III node with two childs
If(curr->left!=NULL&&curr->right!=NULL)
{
Temp=findmax(curr->left)
Swap(curr->data,temp->data)
DeleteNode(curr->left,temp); }
// for case 1 and 2 node with no child and single child
Else
{
Child=(curr->left)?curr->left:curr->right;
If(x<parent->data) parent->left=child;
Else parent->right=child;
Free(curr);
}
}
Write “ node not in tree”
}
25
Trees
To delete 25 in the above tree it is replaced with 22 or 28. If it is replaced with 22 the tree
will be like this after deletion.
22
/ \
20 36
/ / \
10 30 40
/ \ / / \
5 12 28 38 48
/ \ \ / \
1 8 15 45 50
Example
Construct a Binary Search Tree by inserting the following sequence of numbers...
10,12,5,4,20,8,7,15 and 13 Above elements are inserted into a Binary Search Tree as
follows...
26
Trees
The worst case time complexity of search , insert and delete operations is O(h) where h is
height of Binary Search Tree. In worst case, we may have to travel from root to the deepest
leaf node. The height of a skewed tree may become n and the time complexity of search and
insert operation may become O(n).
27
Trees
}
FIND THE NODE WITH maximum VALUE IN A BINARY SEARCH TREE
This is quite simple. Just traverse the node from root to right recursively until right is NULL.
The node whose right is NULL is the node with minimum value.
Minimum(root)
{
Curr=root;
while (current->right != NULL) {
current = current->right;
}
return(current->data);
}
Threaded Binary Trees:
A binary tree is represented using array representation or linked list representation. When a binary
tree is represented using linked list representation, if any node is not having a child we use NULL
pointer in that position. In any binary tree linked list representation, there are more number of NULL
pointer than actual pointers. Generally, in any binary tree linked list representation, if there
are 2N number of reference fields, then N+1 number of reference fields are filled with NULL ( N+1
are NULL out of 2N ). This NULL pointer does not play any role except indicating there is no link (no
child).
new binary tree called "Threaded Binary Tree", which make use of NULL pointer to improve its
traversal processes. In threaded binary tree, NULL pointers are replaced by references to other
nodes in the tree, called threads.
Threaded Binary Tree is also a binary tree in which all left child pointers that are NULL (in Linked list
representation) points to its in-order predecessor, and all right child pointers that are NULL (in
Linked list representation) points to its in-order successor
The idea of threaded binary trees is to make inorder traversal faster and do it without stack and
without recursion.
28
Trees
Left threaded: Where all LEFT NULL pointers is made to point to the inorder predecessor (if
predecessor exists)
Node contains 4 parts. 1. Left thread 2. Left child 3. Data [Link] child
right threaded: Where all right NULL pointers is made to point to the inorder successor (if successor
exists)
Node contains 4 parts. [Link] child 2. Data [Link] child [Link] thread
29
Trees
Double Threaded: Where both left and right NULL pointers are made to point to inorder predecessor
and inorder successor respectively. The predecessor threads are useful for reverse inorder traversal
and postorder traversal.
To convert above binary tree into threaded binary tree, first find the in-order traversal of that tree...
H-D-I-B-E-A-F-J-C-G
Above example binary tree become as follows after converting into threaded binary tree.
Node contains 5 parts. 1. Left thread 2. Left child 3. Data [Link] child 5. Right thread
30