Tree Concepts & Definitions Graph
Tree Concepts & Definitions Graph
5. Undirected Graph
A graph in which every edge is undirected is called undirected graph.
6. Mixed Graph
If some of the edges are directed and some are undirected in graph then the graph is called
mixed graph.
7. Loop direction of a loop is of no significance,
so it can be considered either directed or
An edge of a graph which joins a node undirected. E.g. An edge 2 from node 2
to itself is called a loop (sling). The to itself.
8. Distinct Edges
In the case of directed edges, the two
possible edges between a pair of nodes
which are opposite in direction are
considered distinct. E.g. edges 1 & 2
between nodes 2 & 3 in Figure 2.
9. Parallel Edges
In some directed as well as undirected
graphs, we may have certain pairs of
nodes joined by more than one edges,
such edges are called Parallel edges.
E.g. edges 1 & 2 between nodes 2 & 3
in Figure 2.
10. Multigraph
Any graph which contains some parallel
edges is called multigraph. E.g. graph in
Figure 2
11. Simple Graph
If there is no more than one edge between a pair of nodes (no more than one directed edge in
the case of a directed graph), then such a graph is called a simple graph.
12. Weighted Graph
A graph in which weights are assigned to every edge is called weighted graph.
13. Isolated Node
In a graph, a node which is not adjacent to any other node is called isolated node.
14. Null Graph
A graph containing only isolated nodes are called null graph. In other words set of edges in
null graph is empty.
15. Path of Graph
Let G=(V, E) be a simple digraph such that the terminal node of any edge in the sequence is
the initial node of the edge, if any appearing next in the sequence defined as path of the graph.
16. Length of Path
The number of edges appearing in the sequence of the path is called length of path.
17. Degree of vertex
The no of edges which have V as their terminal node is call as indegree of node V The no of
edges which have V as their initial node is call as outdegree of node V
Sum of indegree and outdegree of node V is called its Total Degree or Degree of vertex.
18. Simple Path (Edge Simple)
A path in a diagraph in which the edges are distinct is called simple path or edge simple. E.g.
path P5 and P6 in Figure 3.
19. Elementary Path (Node Simple)
A path in which all the nodes through which it traverses are distinct is called elementary path.
E.g. paths P1, P2, P3 and P4 in figure 3 are elementary paths. Path P5 & P6 are simple but not
elementary.
20. Cycle (Circuit)
A path which originates and ends in the same node is called cycle (circuit). E.g. C1 = ((2,2)),
C2 = ((1,2),(2,1)), C3 = ((2,3),(3,1),(1,2)).
21. Acyclic Digraph
A simple digraph which does not have any cycle is called acyclic digraph.
TREE
1. Directed Tree
A directed tree is an acyclic digraph
which has one node called its root with
in degree 0, while all other nodes have
in degree 1.
Every directed tree must have at least
one node. An isolated node is also a
directed tree.
2. Terminal Node (Leaf Node)
In a directed tree, any node which has
out degree 0 is called terminal node or
leaf node. All other nodes are called Figure 4
branch nodes.
3. Level of Node
The level of any node is the length of its path from the root.
4. Ordered Tree
In a directed tree an ordering of the nodes at each level is prescribed then such a tree is called
ordered tree.
The diagram below represents same directed tree but different ordered trees.
Figure 5
5. Forest
If we delete the root and its edges connecting the nodes at level 1, we obtain a set of disjoint
tree. A set of disjoint tree is a forest.
6. M-ary Tree
If in a directed tree the out degree of every node is less than or equal to m then tree is called an
m-ary tree.
7. Complete M-ary Tree
If the out degree of each and every node is exactly equal to m or 0 and the number of nodes at
level i is mi then the tree is called a complete m-ary tree.
8. Positional M-ary Tree
If we consider m-ary trees in which the m children of any node are assumed to have m distinct
positions, if such positions are taken into account, then tree is called positional m- ary tree.
9. Height of the tree
The height of a tree is the length of the path from the root to the deepest node in the tree.
10. Sibling
Siblings are nodes that share the same parent node.
11. Binary tree (Figure 6(a))
If in a directed tree the out degree of every node is less than or equal to 2 then tree is called
binary tree.
12. Strictly binary tree (Figure 6(b))
A strictly binary tree (sometimes proper binary tree or 2-tree) is a tree in which every node
other than the leaves has two children.
13. Complete binary tree (Figure 6(c))
If the out degree of each and every node is exactly equal to 2 or 0 and the number of nodes at
level i is 2i then the tree is called a complete binary tree.
14. Almost Complete binary tree (Figure 6(d))
1. The tree is Complete Binary Tree (All nodes) till level (d-1).
2. At level d, (i.e the last level), if a Node is present, then all the Nodes to the left of that node
should also be present.
(a) Binary Tree (b) Strictly (c) Complete Binary (d) Almost
Binary Tree Tree Complete
Binary Tree
Figure 6
Figure 7.1
B. Nesting of Parenthesis
Figure 7.2
Figure 7.3
D. Level-Number Format
Figure 7.4
Binary Tree Traversals (Inorder, Preorder and Postorder)
The most common operation performed on tree structure is that of traversal. This is a procedure by
which each node in the tree is processed exactly once in a systematic manner.
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.
There are three ways of traversing a binary tree.
1. Preorder Traversal
2. Inorder Traversal
3. Postorder Traversal
Preorder: Preorder traversal of a binary tree is defined as follow
Process the root node
Traverse the left subtree in preorder
Traverse the right subtree in preorder
If particular subtree is empty (i.e., node has no left or right descendant) the traversal is
performed by doing nothing, In other words, a null subtree is considered to be fully traversed
when it is encountered.
Preorder traversal : A B C D E F G
Inorder traversal : C B A E F D G
Postorder traversal : C B F E G D A
Converse: If we interchange left and right words in the preceding definitions, we obtain three new
traversal orders which are called Converse Preorder, Converse Inorder and Converse Postorder.
Example
Now the search element 1 in inorder[], say you find it at position i, once you find it, make note
of elements which are left to i (this will construct the leftsubtree) and elements which are right
to i ( this will construct the rightSubtree).
Suppose in previous step, there are X number of elements which are left of „i’ (which will
construct the leftsubtree), take first X elements from the postorder[] traversal, this will be the
post order traversal for elements which are left to i. similarly if there are Y number of elements
which are right of „i‟ (which will construct the rightsubtree), take next Y elements, after X
elements from the postorder[] traversal, this will be the post order traversal for elements which
are right to i
From previous two steps construct the left and right subtree and link it to root.left and root.right
respectively.
Objective: – Given a preorder and postorder traversal, construct a binary tree from that.
Input: preorder and postorder traversals
Appraoch:
Note: It is not possible to construct a general Binary Tree from preorder and postorder traversals. But if
it is known that the tree is strictly binary tree, it is possible to construct the tree without ambiguity.
For example, Preorder and Postorder traversals are same for the trees given in above diagram.
Preorder: AB
Postorder: BA
In preOrder, the leftmost element is root of tree. Since the tree is strictly binary tree and array size is
more than 1. The value next to 1 in preOrder, must be left child of root. So we know 1 is root and 2 is
left child.
How to find the all nodes in left subtree? We know 2 is root of all nodes in left subtree. All nodes
before 2 in postOrder must be in left subtree. Now we know 1 is root, elements {8, 9, 4, 5, 2} are in left
subtree, and the elements {6, 7, 3} are in right subtree.
1
/ \
/ \
{8, 9, 4, 5, 2} {6, 7, 3}
We recursively follow the above approach and get the following tree.
1
/ \
2 3
/ \ / \
4 5 6 7
/ \
8 9
Algorithms for Preorder, Postorder and Inorder traversal of binary tree
Preorder
Procedure : RPREORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as described below, this procedure traverses the tree in preorder, in a recursive manner.
Procedure : PREORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as previously described, this procedure traverses the tree in preorder, in an iterative manner. S
and TOP denote an auxiliary stack and its associated top index, respectively. The pointer variable P
denotes the current node in the tree.
1. [Intialize]
If T= NULL
Then write („EMPTY TREE‟)
Return
Else TOP ← 0
Call PUSH(S,TOP,T)
2. [Process each stacked branch address]
Repeat step 3 while TOP > 0
3. [Get stored address and branch left]
P ← POP(S, TOP)
Repeat while P ≠ NULL
Write (DATA(P))
If RPTR(P) ≠ NULL
Then Call PUSH(S,TOP,RPTR(P)) /* store address of nonempty right subtree */
P ← LPTR(P) /* branch left */
4. [Finished]
Return
Postorder
Procedure : RPOSTORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as previously described, this procedure traverses the tree in postorder, in a recursive manner.
Procedure : POSTORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as previously described, this procedure traverses the tree in postorder, in an iterative manner. S
and TOP denote an auxiliary stack and its associated top index, respectively. The pointer variable P
denotes the current node in the tree.
Here we need two types of stack entries, the first indicating that a left subtree is being traversed, and
the second that a right subtree is being traversed. For convenience we will use negative pointer values
to indicate the second type of entry. This, of course, assumes that valid pointer data are always nonzero
and positive.
1. [Intialize]
If T= NULL
Then write („EMPTY TREE‟)
Return
Else P←T
TOP ← 0
2. [Traverse in postorder]
Repeat thru step 5 while true
3. [Descend left]
Repeat while P ≠ NULL
Call PUSH(S, TOP, P)
P ← LPTR(P)
4. [Process a node whose left and right subtrees have been traversed]
Repeat while S[TOP] < 0
P ← POP(S, TOP)
Write(DATA(P))
If TOP = 0 (Have all nodes been processed?)
Then Return
5. [Branch right and then mark node from which we branched]
P ← RPTR(S[TOP])
S[TOP] ← -S[TOP]
Inorder
Procedure : RINORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as previously described, this procedure traverses the tree in inorder, in a recursive manner.
Procedure : INORDER(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as previously described, this procedure traverses the tree in inorder, in an iterative manner. S and
TOP denote an auxiliary stack and its associated top index, respectively. The pointer variable P denotes
the current node in the tree.
1. [Intialize]
If T= NULL
Then write („EMPTY TREE‟)
Return
Else TOP ← 0
P←T
2. [Traverse in inorder]
Repeat step 3 while TOP > 0 or P ≠ NULL
3. [Descend left]
If P ≠ NULL
Then Call PUSH(S, TOP, P)
P ← LPTR(P)
Else
P ← POP(S, TOP)
Write (DATA(P))
P ← RPTR(P)
4. [Finished]
Return
Algorithm to create duplicate copy of a binary tree
Procedure : COPY(T)
Given a binary tree whose root node address is given by pointer variable T and whose node structure is
same as previously described, this procedure generates a copy of the tree and returns the address of its
root node. NEW is a temporary pointer variable.
1. [Null Pointer?]
If T= NULL
Then Return (NULL)
2. [Create a new node]
NEW <= NODE
3. [Copy information field]
DATA(NEW) ← DATA(T)
4. [Set the structural links]
LPTR(NEW) ← COPY(LPTR(T))
RPTR(NEW) ← COPY(RPTR(T))
5. [Return address of new node]
Return(NEW)
We consider a particular kind of a binary tree called a Binary Search Tree (BST). The basic idea behind
this data structure is to have such a storing repository that provides the efficient way of data sorting,
searching and retrieving.
A BST is a binary tree where nodes are ordered right subtrees of a BST are again search trees;
in the following way: the above definition is recursively applied to all
internal nodes:
Each node contains one key (also
known as data)
The keys in the left subtree are less then
the key in its parent node, in short L <
P;
The keys in the right subtree are greater
the key in its parent node, in short P <
R;
Duplicate keys are not allowed.
In the following tree all nodes in the left subtree
of 10 have keys < 10 while all nodes in the
right subtree > 10. Because both the left and
Algorithm to insert a node into BST
Procedure: BSTINSERT(HEAD, KEY)
Given a lexically ordered binary tree with the node structure previously described and the information
value KEY of the node to be inserted, this procedure inserts the node whose information field is equal
to KEY. PARENT is a pointer variable which denotes the address of the parent of the node to be
inserted. CURRENT denotes the address of the node in focus. Also, the tree assumed to have a list
head whose address is given by HEAD.
1. [Intialize]
If LPTR(HEAD) = HEAD
Then NEW <= NODE
DATA(NEW) ← KEY
LPTR(HEAD) ← NEW
Return
Else CURRENT ← LPTR(HEAD)
PARENT ← HEAD
2. [Traverse tree to find Parent node of key]
Repeat while CURRENT ≠ NULL
PARENT ← CURRENT
If KEY < DATA(CURRENT)
Then CURRENT ← LPTR(CURRENT)
Else CURRENT ← RPTR(CURRENT)
3. [Create a node with key]
If KEY < DATA(PARENT)
Then LPTR(PARENT) <= NODE
DATA(LPTR(PARENT)) ← KEY
Else RPTR(PARENT) <= NODE
DATA(RPTR(PARENT)) ← KEY
4. [Finished]
Return
Example:
Case 1: Deleting a node with no children
Delete a node with key 15
Case 2: Deleting a node with one child
Delete a node with key 5
In above binary tree, there are 7 null pointers & actual 5 pointers. In all there are 12 pointers.
We can generalize it that for any binary tree with n nodes there will be (n+1) null pointers and 2n
total pointers.
The objective here to make effective use of these null pointers.
A. J. perils & C. Thornton jointly proposed idea to make effective use of these null pointers.
According to this idea we are going to replace all the null pointers by the appropriate pointer values
called threads.
And binary tree with such pointers are called threaded tree.
In the memory representation of a threaded binary tree, it is necessary to distinguish between a
normal pointer and a thread.
Therefore we have an alternate node representation for a threaded binary tree which contains five
fields as show bellow:
Head
Two-way threading:
Here, a thread in the left field points to the predecessor node and a thread in right field
points to a successor node, in the inorder traversal of tree T.
Furthermore, the left pointer of the first node and the right pointer of the last node (in the
inorder traversal of T) will contain the null value when T does not have a header node.
Inorder of above tree is: D,B,F,E,A,G,C,L,J,H,K
Below figure shows the threaded binary tree T, when T has a head node
Examples:
1. Draw a right in-threaded binary tree for the given tree.
Advantages
Inorder traversal is faster than unthreaded version as stack is not required.
Effectively determines the predecessor and successor for inorder traversal, for unthreaded
tree this task is more difficult.
A stack is required to provide upward pointing information in tree, which threading
provides.
It is possible to generate successor or predecessor of any node without having over head of
stack with the help of threading.
Disadvantages
Procedure: INP(X)
Given X, the address of a node in a threaded binary tree, this function returns the address of its inorder
predecessor. P is a temporary pointer variable.
Procedure: TINORDER(HEAD)
Given the address of the list head (HEAD) of a binary tree which has been threaded for inorder
traversal and sub algorithm INS previously discussed, this procedure traverses the tree in inorder. P is a
temporary pointer variable.
1. [Initialize]
P ← HEAD
2. [Traverse threaded tree in inorder]
Repeat while true
P ← INS (P)
If P = HEAD
Then Exit
Else Write (DATA(P))
Expression Trees
Expression tree is a strictly binary tree in which each internal node corresponds to operator and
each leaf node corresponds to operand
Binary trees are widely used to store algebraic expressions. For example, consider the algebraic
expression given as: Exp = (a – b) + (c * d)
This expression can be represented using a binary tree as shown in figure below
The Preorder traversal of a binary expression tree yields the prefix form of the expression.
The Postorder traversal of a binary expression tree yields the postfix form of the expression.
The Inorder traversal of a binary expression tree yields the infix form of the expression with the
ordering of the operations implied by the structure of the tree, as such tree does not contain
parenthesis.
For example, two expression trees given below, when traversed in inorder, generate same
expression i.e. A + B * C. But the evaluation of each of them is different
Huffman Coding
Huffman coding is an encoding algorithm developed by David A. Huffman that is widely
used as a lossless data compression technique. The idea is to assign variable-length codes to input
characters; lengths of the assigned codes are based on the frequencies of corresponding characters. The
most frequent character gets the smallest code and the least frequent character gets the largest code.
The variable-length codes assigned to input characters are Prefix Codes, means the codes (bit
sequences) are assigned in such a way that the code assigned to one character is not prefix of code
assigned to any other character. This is how Huffman Coding makes sure that there is no ambiguity
when decoding the generated bit stream.
Let us understand prefix codes with a counter example. Let there be four characters a, b, c and d, and
their corresponding variable length codes be 00, 01, 0 and 1. This coding leads to ambiguity because
code assigned to c is prefix of codes assigned to a and b. If the compressed bit stream is 0001, the de-
compressed output may be “cccd” or “ccb” or “acd” or “ab”.
There are mainly two major parts in Huffman Coding
1) Build a Huffman Tree from input characters.
2) Traverse the Huffman Tree and assign codes to characters.
1. Steps to build Huffman Tree (Huffman Algorithm)
Input is array of unique characters along with their weight or frequency of occurrences and output is
Huffman Tree.
1. Create a leaf node for each character. Add the character and its weight or frequency
of occurrence to the priority queue.
2. Repeat Steps 3 to 5 while the total number of nodes in the queue is greater than 1.
3. Remove two nodes that have the lowest weight (or highest priority).
4. Create a new internal node by merging these two nodes as children and with weight equal to the
sum of the two nodes' weights.
5. Add the newly created node to the queue.
Example: Create a Huffman tree with the following nodes arranged in a priority queue.
Solution:
2. Steps to print codes from Huffman Tree
In the Huffman tree, circles contain the cumulative weights or frequency of occurrences of their child
nodes. Every left branch is coded with 0 and every right branch is coded with 1. So, the characters A,
E, R, W, X, Y, and Z are coded as shown in Table.