DSA Module - 3
DSA Module - 3
In data representation, each column of a sparse matrix is represented as a circularly linked listwith a
header node. A similar representation is used for each row of a sparse matrix.
Each node has a tag field, which is used to distinguish between header nodes and entry nodes.
Header Node:
Each header node has three fields: down, right, and next as shown in figure (a).
The down field is used to link into a column list and the right field to link into a row list.
The next field links the header nodes together.
The header node for row i is also the header node for column i, and the total number of
header nodes is max {number of rows, number of columns}.
Element node:
Each element node has five fields in addition in addition to the tag field: row, col, down, right,
value as shown in figure (b).
The down field is used to link to the next nonzero term in the same column and the right field
to link to the next nonzero term in the same row. Thus, if aij ≠ 0, there is a node with tag
field = entry, value = aij, row = i, and col = j as shown in figure (c).
We link this node into the circular linked lists for row i and column j. Hence, it is
simultaneously linked into two different lists.
Figure (3) shows the linked representation of this matrix. Although we have not shown thevalue of
the tag fields, we can easily determine these values from the node structure.
For each nonzero term of a, have one entry node that is in exactly one row list and one column list.
The header nodes are marked HO-H3. As the figure shows, we use the right field of the header node
list header to link into the list of header nodes.
To represent a numRows x numCols matrix with numTerms nonzero terms, then we need max
{numRows, numCols} + numTerms + 1 nodes. While each node may require several words of memory,
the total storage will be less than numRows x numCols when numTerms is sufficiently small.
There are two different types of nodes in representation, so unions are used to create theappropriate
data structure. The C declarations are as follows:
In a circular linked list, the last node contains a pointer to the first node of the list. We can have a circular
singly linked list as well as a circular doubly linked list. While traversing a circular linked list, we can
begin at any node and traverse the list in any direction, forward or backward, until we reach the same
node where we started. Thus, a circular linked list has no beginning and no ending. Figure 6.26 shows a
circular linked list.
Consider the linked list shown in Fig. 6.29. Suppose we want to add a new node with data 9 as the first
node of the list. Then the following changes will be done in the linked list.
Figure 6.30 shows the algorithm to insert a new node at the beginning of a linked list. In Step 1, we first
check whether memory is available for the new node. If the free memory has exhausted, then an
OVERFLOW message is printed. Otherwise, if free memory cell is available, then we allocate space for
the new node. Set its DATA part with the given VAL and the NEXT part is initialized with the address of
the first node of the list, which is stored in START.
Now, since the new node is added as the first node of the list, it will now be known as the START node,
that is, the START pointer variable will now hold the address of the NEW_NODE.
While inserting a node in a circular linked list, we have to use a while loop to traverse to the last node of
the list. Because the last node contains a pointer to START, its NEXT field is updated so that after
insertion it points to the new node which will be now known as START.
1. The difficulties with single linked lists is that, it is possible to traversal only in one direction,
i.e., direction of the links.
2. The only way to find the node that precedes p is to start at the beginning of the list. The same
problem arises when one wishes to delete an arbitrary node from a singly linked list. Hence
the solution is to use doubly linked list
A doubly linked list or a two-way linked list is a more complex type of linked list which contains a
pointer to the next as well as the previous node in the sequence. Therefore, it consists of three parts—
data, a pointer to the next node, and a pointer to the previous node as shown in Fig. 6.37.
struct node {
The PREV field of the first node and the NEXT field of the last node will contain NULL. The PREV field
is used to store the address of the preceding node, which enables us to traverse the list in the backward
direction.
In this section, we will discuss how a new node is added into an already existing doubly linked list. We
will take four cases and then see how insertion is done in each case.
Consider the doubly linked list shown in Fig. 6.39. Suppose we want to add a new node with data 9 as the
first node of the list. Then the following changes will be done in the linked list.
Figure 6.40 shows the algorithm to insert a new node at the beginning of a doubly linked list. In Step 1,
we first check whether memory is available for the new node. If the free memory has exhausted, then an
OVERFLOW message is printed. Otherwise, if free memory cell is available, then we allocate space for
the new node. Set its DATA part with the given VAL and the NEXT part is initialized with the address of
the first node of the list, which is stored in START.
Now, since the new node is added as the first node of the list, it will now be known as the START node,
that is, the START pointer variable will now hold the address of NEW_NODE.
Figure 6.42 shows the algorithm to insert a new node at the end of a doubly linked list. In Step 6, we take
a pointer variable PTR and initialize it with START. In the while loop, we traverse through the linked list
to reach the last node. Once we reach the last node, in Step 9, we change the NEXT pointer of the last
node to store the address of the new node.
Remember that the NEXT field of the new node contains NULL which signifies the end of the linked list.
The PREV field of the NEW_NODE will be set so that it points to the node pointed by PTR (now the
second last node of the list).
Consider the doubly linked list shown in Fig. 6.47. When we want to delete a node from the beginning of
the list, then the following changes will be done in the linked list.
Figure 6.48 shows the algorithm to delete the first node of a doubly linked list. In Step 1 of the algorithm,
we check if the linked list exists or not. If START = NULL, then it signifies that there are no nodes in the
list and the control is transferred to the last statement of the algorithm.
However, if there are nodes in the linked list, then we use a temporary pointer variable PTR that is set to
point to the first node of the list. For this, we initialize PTR with START that stores the address of the
first node of the list. In Step 3, START is made to point to the next node in sequence and finally the
memory
occupied by PTR (initially the first node of the list) is freed and returned to the free pool.
TREES
DEFINITION
A tree is a finite set of one or more nodes such that
There is a specially designated node called root.
The remaining nodes are partitioned into n >= 0 disjoint set T1,…,Tn, where each of these sets
is a tree. T1,…,Tn are called the subtrees of the root.
TERMINOLOGY
Parent and Children: Suppose N is a node in T with left successor S1 and right successor S2,
then N is called the Parent (or father) of S1 and S2. Here, S1 is called left child (or Son) and S2
is called right child (or Son) of N.
Siblings: Children of the same parent are said to be siblings.
Edge: A line drawn from node N of a T to a successor is called an edge
Path: A sequence of consecutive edges from node N to a node M is called a path.
Ancestors of a node: All the nodes along the path from the root to that node.
The level of a node: defined by letting the root be at level zero. If a node is at level l, then it
children are at level l+1.
Height (or depth): The maximum level of any node in the tree
Representation of Trees
Figure (A)
1. List Representation
2. Left Child- Right Sibling Representation
3. Representation as a Degree-Two tree
List Representation:
The tree can be represented as a List. The tree of figure (A) could be written as the list.
(A (B (E (K, L), F), C (G), D (H (M), I, J) ) )
Tree node is represented by a memory node that has fields for the data and pointers to the treenode's
children
Since the degree of each tree node may be different, so memory nodes with a varying number of
For a tree of degree k, the node structure can be represented as below figure. Each child field is
used to point to a subtree.
The below figure show the node structure used in the left child-right sibling representation
To obtain the degree-two tree representation of a tree, simply rotate the right-sibling pointers in a
left child-right sibling tree clockwise by 45 degrees. This gives us the degree-two tree displayed in
Figure (E).
In the degree-two representation, a node has two children as the left and right children.
BINARY TREES
Definition: A binary tree T is defined as a finite set of nodes such that,
T is empty or
T consists of a root and two disjoint binary trees called the left subtree and the right
subtree.
1. Skewed Tree
A skewed tree is a tree, skewed to the left or skews to the right.
or
It is a tree consisting of only left subtree or only right subtree.
A tree with only left subtrees is called Left Skewed Binary Tree.
A tree with only right subtrees is called Right Skewed Binary Tree.
Figure (a): Skewed binary tree Figure (b): Complete binary tree
The following tree is its extended binary tree. The circles represent internal nodes, and square
represent external nodes.
Every internal node in the extended tree has exactly two children, and every external node is a
leaf. The result is a complete binary tree.
Proof:
(1) The proof is by induction on i.
Induction Base: The root is the only node on level i = 1. Hence, the maximum number of nodes on
level i =1 is 2i-1 = 20 = 1.
Induction Hypothesis: Let i be an arbitrary positive integer greater than 1. Assume that the maximum
number of nodes on level i -1is 2i-2
Induction Step: The maximum number of nodes on level i -1 is 2i-2 by the induction hypothesis.
Since each node in a binary tree has a maximum degree of 2, the maximum number of nodes on
level i is two times the maximum number of nodes on level i-1, or 2i-1
Proof: Let n1 be the number of nodes of degree one and n the total number of nodes.
Since all nodes in T are at most of degree two, we have
n = n0 + n1+ n2 (1)
Count the number of branches in a binary tree. If B is the number of branches, then n
=B + 1.
All branches stem from a node of degree one or two. Thus,
B = n 1+ 2n2.
Hence, we obtain
n = B + 1= n 1+ 2n2 + 1 (2)
Subtracting Eq. (2) from Eq. (1) and rearranging terms, we get
n0 = n2 +1
In the computer’s memory, a binary tree can be maintained either by using a linked representation or by
using a sequential representation.
Linked representation of binary trees In the linked representation of a binary tree, every node will have
three parts: the data element, a pointer to the left node, and a pointer to the right node. So in C, the binary
tree is built with a node type given below.
struct node {
struct node *left;
int data ;
struct node *right;
};
Every binary tree has a pointer ROOT, which points to the root element (topmost element) of the tree. If
ROOT = NULL, then the tree is empty. Consider the binary tree given in Fig. 9.3. The schematic diagram
of the linked representation of the binary tree is shown in Fig. 9.9.
Sequential representation of trees is done using single or one-dimensional arrays. Though it is the
simplest technique for memory representation, it is inefficient as it requires a lot of memory space. A
sequential binary tree follows the following rules:
Let ptr is the pointer which contains the location of the node N currently being scanned. L(N) denotes the
leftchild of node N and R(N) is the right child of node N
1. Preorder: Preorder is the procedure of visiting a node, traverse left and continue. When you cannot
continue, move right and begin again or move back until you can move right and resume.
Recursion function:
In Figs (a) and (b), find the sequence of nodes that will be visited using pre-order traversal algorithm.
2. Inorder: Inorder traversal calls for moving down the tree toward the left until you cannot go further.
Then visit the node, move one node to the right and continue. If no move can be done, then go back one
more node.
Recursion function:
The inorder traversal of a binary tree can be recursively defined as
Traverse the left subtree in inorder.
Visit the root.
Traverse the rig
For the trees given in below, find the sequence of nodes that will be visited using in-order traversal
algorithm.
3. Postorder: Postorder traversal calls for moving down the tree towards the left until you can go no
further. Then move to the right node and then visit the node and continue.
Recursion function:
The Postorder traversal of a binary tree can be recursively defined as
Traverse the left subtree in postorder.
Traverse the right subtree in postorder.
Visit the root
For the trees given in below, find the sequence of nodes that will be visited using post-order traversal
algorithm.
6. Level-Order traversal:
7.
Visiting the nodes using the ordering suggested by the node numbering is called level ordering traversing.
The nodes in a tree are numbered starting with the root on level 1 and so on.
Firstly visit the root, then the root’s left child, followed by the root’s right child. Thus continuing in this
manner, visiting the nodes at each new level from the leftmost node to the rightmost node.
Initially in the code for level order add the root to the queue. The function operates by deleting the node at
the front of the queue, printing the nodes data field and adding the nodes left and right children to the
queue.
Expression Trees
Binary trees are widely used to store algebraic expressions. For example, consider the algebraic
expression given as:
Given an expression, Exp = ((a + b) – (c * d)) % ((e ^f) / (g – h)), construct the corresponding binary tree.
e f g h
e
e
e
Given the binary tree, write down
e the expression that it represents.
e
e
e
e
Use the operator precedence chart to find the sequence in which operations will be performed. The given
expression can be written as
In the linked representation of any binary tree, there are more null links than actual pointers. These
null links are replaced by the pointers, called threads, which points to other nodes in the tree.
1. Assume that ptr represents a node. If ptr→leftChild is null, then replace the null link
with a pointer to the inorder predecessor of ptr.
2. If ptr →rightChild is null, replace the null link with a pointer to the inorder successor ofptr.
Ex: Consider the binary tree as shown in below figure:
In above figure the new threads are drawn in broken lines. This tree has 9 node and 10 0 -links which
has been replaced by threads.
When trees are represented in memory, it should be able to distinguish between threads and
pointers. This can be done by adding two additional fields to node structure, ie., leftThread and
rightThread
If ptr→leftThread = TRUE, then ptr→leftChild contains a thread, otherwise it contains a
pointer to the left child.
If ptr→rightThread = TRUE, then ptr→rightChild contains a thread, otherwise it contains a
pointer to the right child.
Node Structure:
The node structure is given in C declaration
The complete memory representation for the tree of figure is shown in Figure C
The variable root points to the header node of the tree, while root →leftChild points to thestart
of the first node of the actual tree. This is true for all threaded trees. Here the problem of the loose
threads is handled by pointing to the head node called root.
By using the threads, an inorder traversal can be performed without making use of astack.
For any node, ptr, in a threaded binary tree, if ptr→rightThread =TRUE, the inorder
successor of ptr is ptr →rightChild by definition of the threads. Otherwise we obtain the
inorder successor of ptr by following a path of left-child links from the right-
child of ptr until we reach a node with leftThread = TRUE.
The function insucc ( ) finds the inorder successor of any node in a threaded tree
without using a stack.