TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 1
Tulsiramji Gaikwad-Patil College of Engineering and Technology
Department of Computer Science and Engineering
Semester : B.E. Fourth Semester
Subject : DSPD
Solution Set: Summer 2016
1. Give the snapshot of following elements using quick sort. Algo specify its time
complexity in all cases.
21 06 56 61 44 07 09 76 75 32
The quick sort uses divide and conquer to gain the same advantages as the merge sort, while not using
additional storage. As a trade-off, however, it is possible that the list may not be divided in half. When
this happens, we will see that performance is diminished.
A quick sort first selects a value, which is called the pivot value. Although there are many different
ways to choose the pivot value, we will simply use the first item in the list. The role of the pivot value
is to assist with splitting the list. The actual position where the pivot value belongs in the final sorted
list, commonly called the split point, will be used to divide the list for subsequent calls to the quick
sort.
Figure 12 shows that 54 will serve as our first pivot value. Since we have looked at this example a few
times already, we know that 54 will eventually end up in the position currently holding 31.
The partitionprocess will happen next. It will find the split point and at the same time move other
items to the appropriate side of the list, either less than or greater than the pivot value.
Partitioning begins by locating two position markers—let’s call them leftmark and rightmark—at the
beginning and end of the remaining items in the list (positions 1 and 8 in Figure 13). The goal of the
partition process is to move items that are on the wrong side with respect to the pivot value while also
converging on the split point. Figure 13 shows this process as we locate the position of 54.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 2
We begin by incrementing leftmark until we locate a value that is greater than the pivot value. We then
decrement rightmark until we find a value that is less than the pivot value. At this point we have
discovered two items that are out of place with respect to the eventual split point. For our example,
this occurs at 93 and 20. Now we can exchange these two items and then repeat the process again.
At the point where rightmark becomes less than leftmark, we stop. The position of rightmark is now
the split point. The pivot value can be exchanged with the contents of the split point and the pivot
value is now in place (Figure 14). In addition, all the items to the left of the split point are less than the
pivot value, and all the items to the right of the split point are greater than the pivot value. The list can
now be divided at the split point and the quick sort can be invoked recursively on the two halves.
The quickSort function shown in ActiveCode 1 invokes a recursive
function, quickSortHelper.quickSortHelper begins with the same base case as the merge sort. If the
length of the list is less than or equal to one, it is already sorted. If it is greater, then it can be
partitioned and recursively sorted. Thepartition function implements the process described earlier.
2.Write a 'C' program to sort the elements of matrix row-wise. Assume that
the matrix is represented by two dimensional array.
// A utility function to youngify a Young Tableau. This is different
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 3
// from standard youngify. It assumes that the value at mat[0][0] is
// infinite.
void youngify(int mat[][N], int i, int j)
{
// Find the values at down and right sides of mat[i][j]
int downVal = (i+1 < N)? mat[i+1][j]: INF;
int rightVal = (j+1 < N)? mat[i][j+1]: INF;
// If mat[i][j] is the down right corner element, return
if (downVal==INF && rightVal==INF)
return;
// Move the smaller of two values (downVal and rightVal) to
// mat[i][j] and recur for smaller value
if (downVal < rightVal)
{
mat[i][j] = downVal;
mat[i+1][j] = INF;
youngify(mat, i+1, j);
}
else
{
mat[i][j] = rightVal;
mat[i][j+1] = INF;
youngify(mat, i, j+1);
}
}
// A utility function to extract minimum element from Young tableau
int extractMin(int mat[][N])
{
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 4
int ret = mat[0][0];
mat[0][0] = INF;
youngify(mat, 0, 0);
return ret;
}
// This function uses extractMin() to print elements in sorted order
void printSorted(int mat[][N])
{
cout << "Elements of matrix in sorted order \n";
for (int i=0; i<N*N; i++)
cout << extractMin(mat) << " ";
}
// driver program to test above function
int main()
{
int mat[N][N] = { {10, 20, 30, 40},
{15, 25, 35, 45},
{27, 29, 37, 48},
{32, 33, 39, 50},
};
printSorted(mat);
return 0;
}
Run on IDE
Output:
Elements of matrix in sorted order
10 15 20 25 27 29 30 32 33 35 37 39 40 45 48 50
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 5
2. Search the following elements using linear search as well as binary search.
Give the step by step representation for successful as well as unsuccessful
search. Algo specify time complexity of both
80 75 45 90 30 40 12 15 93 08
bool jw_search ( int *list, int size, int key, int*& rec )
{
// Linear Search
bool found = false;
int i;
for ( i = 0; i < size; i++ ) {
if ( key == list[i] )
break;
}
if ( i < size ) {
found = true;
rec = &list[i];
}
return found;
}
Complexity
Best case: 1 step
Average case: n/2 steps
Worse case: n steps
Binary search
bool jw_search ( int *list, int size, int key, int*& rec )
{
// Binary search
bool found = false;
int low = 0, high = size - 1;
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 6
while ( high >= low ) {
int mid = ( low + high ) / 2;
if ( key < list[mid] )
high = mid - 1;
else if ( key > list[mid] )
low = mid + 1;
else {
found = true;
rec = &list[mid];
break;
}
}
return found;
}
Best case: log2n steps (could be 1 step)
Average case: log2n steps (could be log2n / 2 steps)
Worse case: log2n steps
3A)
Explain with example:
i) Circular linked list
In a standard queue data structure re-buffering problem occurs for each dequeue operation. To solve
this problem by joining the front and rear ends of a queue to make the queue as a circular queue
Circular queue is a linear data structure. It follows FIFO principle.
In circular queue the last node is connected back to the first node to make a circle.
Circular linked list fallow the First In First Out principle
Elements are added at the rear end and the elements are deleted at front end of the queue
Both the front and the rear pointers points to the beginning of the array.
It is also called as “Ring buffer”.
Items can inserted and deleted from a queue in O(1) time.
Circular Queue can be created in three ways they are
Using single linked list
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 7
Using double linked list
Using arrays
Using single linked list:
It is an extension for the basic single linked list. In circular linked list Instead of storing a Null value in
the last node of a single linked list, store the address of the 1st node (root) forms a circular linked list.
Using circular linked list it is possible to directly traverse to the first node after reaching the last node.
The following figure shows circular single linked list:
Using double linked list
In double linked list the right side pointer points to the next node address or the address of first node
and left side pointer points to the previous node address or the address of last node of a list. Hence the
above list is known as circular double linked list.
The following figure shows Circular Double linked list :-
b)
Doubly linked list
from one node to other node only in one direction and we can not traverse back. We can solve this
kind of problem by using double linked list. Double linked list can be defined as follows...
Double linked list is a sequence of elements in which every element has links to its previous element
and next element in the sequence.
In double linked list, every node has link to its previous node and next node. So, we can traverse
forward by using next field and can traverse backward by using previous field. Every node in a double
linked list contains three fields and they are shown in the following figure...
Here, 'link1' field is used to store the address of the previous node in the sequence, 'link2' field is
used to store the address of the next node in the sequence and 'data' field is used to store the actual
value of that node.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 8
Example
NOTE
☀ In double linked list, the first node must be always pointed by head.
☀ Always the previous field of the first node must be NULL.
☀ Always the next field of the last node must be NULL.
Operations
In a double linked list, we perform the following operations...
1. Insertion
2. Deletion
3. Display
4.
3) Generalized linked list
Current implementation of lists: – Finite sequence of zero or more atomic elements A = (a 0, a 1, a
2 …. an-1 ) – Elements of list are restricted to atoms: • Individual pieces of information – An
integer, A Rectangle • Only structural property of a list is position – Given position, can easily
access data • Very much like arrays Generalized Lists • Relax the assumption of atomic elements: –
Lists can now be composed of atoms or lists – Definition: A generalized list A is a finite sequence
of zero or more elements a 0, a 1, …, an-1 where ai is either an atom or a list. Elements that are not
atomic are called sublists of A. Generalized Lists • Conventions for Generalized Lists: – List names
are represented in capital letters – Atom names are lowercase letters • Definitions for Generalized
Lists: Length – Number of elements (atoms or sublists) in the list If length > 0 Head – First element
of the list Tail – List composed of all elements except first of list Generalized Lists • Examples of
Generalized Lists: – D = ( ) Length 0, Null List – A = (a, (b,c)) Length 2 Head = a Tail = ((b,c)) – B
= (A, A, ()) Length 3 Head = A Tail = (A,()) – C = (a, C) Length 2 Head = a Tail = (C)
b) Write an algorithm to search an element in singly linked list.
Step-1: Initialise the Current pointer with the beginning of the List.
Step-2: Compare the KEY value with the Current node value;
if they match then quit there
else go to step-3.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 9
Step-3: Move the Current pointer to point to the next node in the list and go to step-2, till the list is not
over or else quit.
Or
Iterative Solution
2) Initialize a node pointer, current = head.
3) Do following while current is not NULL
a) current->key is equal to the key being searched return true.
b) current = current->next
4) Return false
4 a) Write a 'C' function to reverse the links of singly linked list.
#include<stdio.h>
#include<stdlib.h>
/* Link list node */
struct node
{
int data;
struct node* next;
};
/* Function to reverse the linked list */
static void reverse(struct node** head_ref)
{
struct node* prev = NULL;
struct node* current = *head_ref;
struct node* next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
/* Function to push a node */
void push(struct node** head_ref, int new_data)
{
/* allocate node */
struct node* new_node =
(struct node*) malloc(sizeof(struct node));
/* put in the data */
new_node->data = new_data;
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 10
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* Function to print linked list */
void printList(struct node *head)
{
struct node *temp = head;
while(temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
/* Driver program to test above function*/
int main()
{
/* Start with the empty list */
struct node* head = NULL;
push(&head, 20);
push(&head, 4);
push(&head, 15);
push(&head, 85);
printf("Given linked list\n");
printList(head);
reverse(&head);
printf("\nReversed Linked list \n");
printList(head);
getchar();
}
Run on IDE
Given linked list
85 15 4 20
Reversed Linked list
20 4 15 85
Time Complexity: O(n) Space Complexity: O(1)
b) Write an algorithm for insertion in the doubly linked list.
i) Insertion at beginning.
ii) Insertion at eng
iii) Insertion at specific location.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 11
Inserting At Beginning of the list
We can use the following steps to insert a new node at beginning of the double linked list...
Step 1: Create a newNode with given value and newNode → previous as NULL.
Step 2: Check whether list is Empty (head == NULL)
Step 3: If it is Empty then, assign NULL to newNode → next and newNode to head.
Step 4: If it is not Empty then, assign head to newNode → next and newNode to head.
Inserting At End of the list
We can use the following steps to insert a new node at end of the double linked list...
Step 1: Create a newNode with given value and newNode → next as NULL.
Step 2: Check whether list is Empty (head == NULL)
Step 3: If it is Empty, then assign NULL to newNode → previous and newNode to head.
Step 4: If it is not Empty, then, define a node pointer temp and initialize with head.
Step 5: Keep moving the temp to its next node until it reaches to the last node in the list (until
temp → next is equal to NULL).
Step 6: Assign newNode to temp → next and temp to newNode → previous.
Inserting At Specific location in the list (After a Node)
We can use the following steps to insert a new node after a node in the double linked list...
Step 1: Create a newNode with given value.
Step 2: Check whether list is Empty (head == NULL)
Step 3: If it is Empty then, assign NULL to newNode → previous & newNode → next and
newNode to head.
Step 4: If it is not Empty then, define two node pointers temp1 & temp2 and initialize temp1
with head.
Step 5: Keep moving the temp1 to its next node until it reaches to the node after which we
want to insert the newNode (until temp1 → data is equal to location, here location is the node
value after which we want to insert the newNode).
Step 6: Every time check whether temp1 is reached to the last node. If it is reached to the last
node then display 'Given node is not found in the list!!! Insertion not possible!!!' and
terminate the function. Otherwise move the temp1 to next node.
Step 7: Assign temp1 → next to temp2, newNode to temp1 → next, temp1 to newNode →
previous, temp2 to newNode → next and newNode to temp2 → previous.
5) In a circular queue represented by an array, how can one specify the number of elements in
the queue in terms of front, rear and MaxQ? Write a 'C' function to delete the element from the
circular queue.
A Circular Queue can be defined as follows...
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 12
Circular Queue is a linear data structure in which the operations are performed based on FIFO (First In
First Out) principle and the last position is connected back to the first position to make a circle.
Graphical representation of a circular queue is as follows...
Implementation of Circular Queue
To implement a circular queue data structure using array, we first perform the following steps before
we implement actual operations.
Step 1: Include all the header files which are used in the program and define a constant
'SIZE' with specific value.
Step 2: Declare all user defined functions used in circular queue implementation.
Step 3: Create a one dimensional array with above defined SIZE (int cQueue[SIZE])
Step 4: Define two integer variables 'front' and 'rear' and initialize both with '-1'. (int front =
-1, rear = -1)
Step 5: Implement main method by displaying menu of operations list and make suitable
function calls to perform operation selected by the user on circular queue.
enQueue(value) - Inserting value into the Circular Queue
In a circular queue, enQueue() is a function which is used to insert an element into the circular queue.
In a circular queue, the new element is always inserted at rear position. The enQueue() function takes
one integer value as parameter and inserts that value into the circular queue. We can use the following
steps to insert an element into the circular queue...
Step 1: Check whether queue is FULL. ((rear == SIZE-1 && front == 0) || (front ==
rear+1))
Step 2: If it is FULL, then display "Queue is FULL!!! Insertion is not possible!!!" and
terminate the function.
Step 3: If it is NOT FULL, then check rear == SIZE - 1 && front != 0 if it is TRUE, then
set rear = -1.
Step 4: Increment rear value by one (rear++), set queue[rear] = value and check 'front == -
1' if it is TRUE, then set front = 0.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 13
deQueue() - Deleting a value from the Circular Queue
In a circular queue, deQueue() is a function used to delete an element from the circular queue. In a
circular queue, the element is always deleted from front position. The deQueue() function doesn't take
any value as parameter. We can use the following steps to delete an element from the circular queue...
Step 1: Check whether queue is EMPTY. (front == -1 && rear == -1)
Step 2: If it is EMPTY, then display "Queue is EMPTY!!! Deletion is not possible!!!" and
terminate the function.
Step 3: If it is NOT EMPTY, then display queue[front] as deleted element and increment the
front value by one (front ++). Then check whether front == SIZE, if it is TRUE, then set
front = 0. Then check whether both front - 1 and rear are equal (front -1 == rear), if it
TRUE, then set both front and rear to '-1' (front = rear = -1).
display() - Displays the elements of a Circular Queue
We can use the following steps to display the elements of a circular queue...
Step 1: Check whether queue is EMPTY. (front == -1)
Step 2: If it is EMPTY, then display "Queue is EMPTY!!!" and terminate the function.
Step 3: If it is NOT EMPTY, then define an integer variable 'i' and set 'i = front'.
Step 4: Check whether 'front <= rear', if it is TRUE, then display 'queue[i]' value and
increment 'i' value by one (i++). Repeat the same until 'i <= rear' becomes FALSE.
Step 5: If 'front <= rear' is FALSE, then display 'queue[i]' value and increment 'i' value by
one (i++). Repeat the same until'i <= SIZE - 1' becomes FALSE.
Step 6: Set i to 0.
Step 7: Again display 'cQueue[i]' value and increment i value by one (i++). Repeat the same
until 'i <= rear' becomes FALSE.
6. a) Explain :
i) Priority queue
ii) Double ended queue
Double Ended Queue (Dequeue):- Double Ended Queue is also a Queue data structure in which the
insertion and deletion operations are performed at both the ends (front and rear). That means, we can
insert at both front and rear positions and can delete from both front and rear positions.
Double Ended Queue can be represented in TWO ways, those are as follows...
1. Input Restricted Double Ended Queue
2. Output Restricted Double Ended Queue
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 14
Input Restricted Double Ended Queue
In input restricted double ended queue, the insertion operation is performed at only one end and
deletion operation is performed at both the ends.
Output Restricted Double Ended Queue
In output restricted double ended queue, the deletion operation is performed at only one end and
insertion operation is performed at both the ends.
Priority queue
Priority queue is a linear data structure. It is having a list of items in which each item
has associated priority. It works on a principle add an element to the queue with an
associated priority and remove the element from the queue that has the highest
priority. In general different items may have different priorities.
b) Write 'C' function for push' POP operation in stack. Also explain the applications of a
stack.
Pop Fuction
void pop()
{
int item;
if(top==-1)
{
printf("\n Stack is empty");
}
else
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 15
{
item=stack[top];
printf("\n item popped is=%d", item);
top--;
}
}
Implementation of stack using'c'
/* static implementation of stack*/
#include<stdio.h>
#include<conio.h>
#define size 5
int stack[size];
int top;
void push()
{
int n;
printf("\n Enter item in stack");
scanf("%d",&n);
if(top==size-1)
{
printf("\nStack is Full");
}
else
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 16
{
top=top+1;
stack[top]=n;
}
}
void pop()
{
int item;
if(top==-1)
{
printf("\n Stack is empty");
}
else
{
item=stack[top];
printf("\n item popped is=%d", item);
top--;
}
}
void display()
{
int i;
printf("\n item in stack are");
for(i=top; i>=0; i--)
printf("\n %d", stack[i]);
}
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 17
void main()
{
char ch,ch1;
ch ='y';
ch1='y';
top=-1;
clrscr();
while(ch!='n')
{
push();
printf("\n Do you want to push any item in stack y/n");
ch=getch();
}
display();
while(ch1!='n')
{
printf("\n Do you want to delete any item in stack y/n");
ch1=getch();
pop();
}
display();
getch();
}
7b) Write a 'C' function to determine the depth of the binary tree as well as to count the
number of leaf nodes in the tree.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 18
/*
* C Program to Find the Number of Nodes in a Binary Tree
*/
#include <stdio.h>
#include <stdlib.h>
/*
* Structure of node
*/
struct btnode
{
int value;
struct btnode *l;
struct btnode *r;
};
void createbinary();
void preorder(node *);
int count(node*);
node* add(int);
typedef struct btnode node;
node *ptr, *root = NULL;
int main()
{
int c;
createbinary();
preorder(root);
c = count(root);
printf("\nNumber of nodes in binary tree are:%d\n", c);
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 19
}
/*
* constructing the following binary tree
* 50
* / \
* 20 30
* / \
* 70 80
* / \ \
*10 40 60
*/
void createbinary()
{
root = add(50);
root->l = add(20);
root->r = add(30);
root->l->l = add(70);
root->l->r = add(80);
root->l->l->l = add(10);
root->l->l->r = add(40);
root->l->r->r = add(60);
}
/*
* Add the node to binary tree
*/
node* add(int val)
{
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 20
ptr = (node*)malloc(sizeof(node));
if (ptr == NULL)
{
printf("Memory was not allocated");
return;
}
ptr->value = val;
ptr->l = NULL;
ptr->r = NULL;
return ptr;
}
/*
* counting the number of nodes in a tree
*/
int count(node *n)
{
int c = 1;
if (n == NULL)
return 0;
else
{
c += count(n->l);
c += count(n->r);
return c;
}
}
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 21
/*
* Displaying the nodes of tree in preorder
*/
void preorder(node *t)
{
if (t != NULL)
{
printf("%d->", t->value);
preorder(t->l);
preorder(t->r);
}
}
/*
* Binary tree
* 50
* / \
* 20 30
* / \
* 70 80
* / \ \
*10 40 60
*/
$ gcc test2.c
$ a.out
50->20->70->10->40->80->60->30
Number of nodes in binary tree are:8
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 22
maxDepth()
1. If tree is empty then return 0
2. Else
(a) Get the max depth of left subtree recursively i.e.,
call maxDepth( tree->left-subtree)
(a) Get the max depth of right subtree recursively i.e.,
call maxDepth( tree->right-subtree)
(c) Get the max of max depths of left and right
subtrees and add 1 to it for the current node.
max_depth = max(max dept of left subtree,
max depth of right subtree)
+ 1
(d) Return max_depth
See the below diagram for more clarity about execution of the recursive function maxDepth() for
above example tree.
maxDepth('1') = max(maxDepth('2'), maxDepth('3')) + 1
= 2 + 1
/ \
/ \
/ \
/ \
/ \
maxDepth('1') maxDepth('3') = 1
= max(maxDepth('4'), maxDepth('5')) + 1
= 1 + 1 = 2
/ \
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 23
/ \
/ \
/ \
/ \
maxDepth('4') = 1 maxDepth('5') = 1
8. a) What is height balanced tree? Explain what you mean by balance factor. Construct a
height balanced tree from the following sequence of integer.
40 30 20 10 05 50 60 80 70
1.1 General Presentation Height balanced trees (or AVL trees) is named after its two inventors, G.M.
Adelson-Velskii and E.M. Landis, who published it in their 1962 paper "An algorithm for the
organization of information." As the name sugests AVL trees are used for organizing information.
AVL trees are used for performing search operations on high dimension external data storage. For
example, a phone call list may generate a huge database which may be recorded only on external
hard drives, hard-disks or other storage devices. AVL is a data structure that allows storing data
such that it may be used efficiently regarding the operations that may be performed and the
resources that are needed. AVL trees are binary search trees, wich have the balance propriety. The
balance property is true for any node and it states: “the height of the left subtree of any node
differs from the height of the right subtree by 1”. The structure of the nodes of a balanced tree can
be represented like: struct NodeAVL{ int key; int ech; nod *left, *right; }; Where: - key represents
the tag of the node(integer number), - ech represents the balancing factor - left and right represent
pointers to the left and right children. Here are some important notions: [1] The lenght of the
longest road from the root node to one of the terminal nodes is what we call the height of a tree.
[2] The difference between the height of the right subtree and the height of the left subtree is what
we call the balancing factor. [3] The binary tree is balanced when all the balancing factors of all
the nodes are -1,0,+1. Formally, we can translate this to this: | hd – hs | ≤ 1, node X being any
node in the tree, where hs and hd represent the heigts of the left and the right subtrees.
b)
Algorithm: buildTree()
1) Pick an element from Preorder. Increment a Preorder Index Variable (preIndex in below code) to
pick next element in next recursive call.
2) Create a new tree node tNode with the data as picked element.
3) Find the picked element’s index in Inorder. Let the index be inIndex.
4) Call buildTree for elements before inIndex and make the built tree as left subtree of tNode.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 24
5) Call buildTree for elements after inIndex and make the built tree as right subtree of tNode.
6) return tNode.
9. a) Describe DFS algorithm. Find out the DFS traversal of the following graph starting at
node A.
DFS (Depth First Search)
DFS traversal of a graph, produces a spanning tree as final result. Spanning Tree is a graph without
any loops. We use Stack data structure with maximum size of total number of vertices in the graph
to implement DFS traversal of a graph.
We use the following steps to implement DFS traversal...
Step 1: Define a Stack of size total number of vertices in the graph.
Step 2: Select any vertex as starting point for traversal. Visit that vertex and push it on to the
Stack.
Step 3: Visit any one of the adjacent vertex of the verex which is at top of the stack which is
not visited and push it on to the stack.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 25
Step 4: Repeat step 3 until there are no new vertex to be visit from the vertex on top of the
stack.
Step 5: When there is no new vertex to be visit then use back tracking and pop one vertex
from the stack.
Step 6: Repeat steps 3, 4 and 5 until stack becomes Empty.
Step 7: When stack becomes Empty, then produce final spanning tree by removing unused edges from
the graph
b) Write an Bellman ford Algorithm to find single source shortest path in a graph.
Introduction
This post about Bellman Ford Algorithm is a continuation of the post Shortest Path Using Dijkstra’s
Algorithm. While learning about the Dijkstra’s way, we learnt that it is really efficient an algorithm to
find the single source shortest path in any graph provided it has no negative weight edges and no
negative weight cycles.
The running time of the Dijkstra’s Algorithm is also promising, O(E +VlogV) depending on our
choice of data structure to implement the required Priority Queue.
Why Bellman Ford Algorithm?
There can be scenarios where a graph may contain negative weight cycles, of course we do not see this
in a real life simpler graph problems where we need to find the shortest or the cheapest paths between
cities etc. But yes, there are complex real life applications where we will have scenarios like negative
edges and negative edge cycles. Few of them are Linear Programming or Solving the Difference
Constraints (for VLSI designs etc) or Detecting Network Failures.
Understanding the meaning of negative edge weights in a graph
I am sure at first it is very difficult to understand the significance of a negative edge weight. But
consider the below scenario:
A student trying to manage his expenses, where he has to work part time to pay for his fee. His
situation and the maintenance of account can be represented by a graph where the money he earns
during a period can be represented by a positive edge weight and the money he spends can be a
negative edge weight.
There can be many similar situations where we can see negative edge weights and sometimes negative
weight cycles.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 26
What is Negative Weight Cycle
A negative weight cycle means that if we add the weights of all the edges in the cycle the sum will
turn up to be a negative number. See the below graph, it contains a negative weight cycle (C, G, H, C)
with weight -4.
So, how is Bellman Ford solving the negative weight cycles problem?
Actually its not, the algorithm cannot solve this problem and cannot give you a definite path. It is
theoretically impossible to find out the shortest path if there exists a negative weight cycle. If you
happen to find the shortest path, then you can go through the negative cycle once more and get a
smaller path. You can keep repeating this step and go through the cycle every time and reduce the total
weight of the path to negative infinity.
So, in practical scenarios, this algorithm will either give you a valid shortest path or will indicate
that there is a negative weight cycle. Explanation – Shortest Path Using Bellman Ford Algorithm
We can use Bellman Ford for directed as well as un-directed graphs. Let us solve a problem using
directed graphs here. The idea of the algorithm is fairly simple.
1. It maintains a list of unvisited vertices.
2. It chooses a vertex (the source) and assigns a maximum possible cost (i.e. infinity) to every
other vertex.
3. The cost of the source remains zero as it actually takes nothing to reach from the source vertex
to itself.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 27
4. In every subsequent iteration of the algorithm it tries to relax each edge in the graph (by
minimizing the cost of the vertex on which the edge is incident).
5. It repeats step 4 for |V|-1 times. By the last iteration we would have gotten some shortest path
from Source to each vertex.
The formula for relaxation remains same as Dijkstra’s Algorithm.
So, why does the outer loop runs |V| – 1 times?
The argument would be, that the shortest path in the graph with |V| vertices cannot be more lengthy
than |V| – 1. So, if we relax all the edges |V| – 1 times, we would have covered all possibilities of
relaxing the edges and we would be left with all shortest paths. There are many proofs by Induction
available in case you are more interested. Or you can look forward for my next post about “The
correctness of Bellman Ford Algorithm”.
10. a) Explain with example.
i) Hamiltonian cycle
Hamiltonian Path in an undirected graph is a path that visits each vertex exactly once. A
Hamiltonian cycle (or Hamiltonian circuit) is a Hamiltonian Path such that there is an edge (in graph)
from the last vertex to the first vertex of the Hamiltonian Path. Determine whether a given graph
contains Hamiltonian Cycle or not. If it contains, then print the path. Following are the input and
output of the required function.
Input:
A 2D array graph[V][V] where V is the number of vertices in graph and graph[V][V] is adjacency
matrix representation of the graph. A value graph[i][j] is 1 if there is a direct edge from i to j,
otherwise graph[i][j] is 0.
Output:
An array path[V] that should contain the Hamiltonian Path. path[i] should represent the ith vertex in
the Hamiltonian Path. The code should also return false if there is no Hamiltonian Cycle in the graph.
For example, a Hamiltonian Cycle in the following graph is {0, 1, 2, 4, 3, 0}. There are more
Hamiltonian Cycles in the graph like {0, 3, 4, 2, 1, 0}
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3)-------(4)
And the following graph doesn’t contain any Hamiltonian Cycle.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 28
(0)--(1)--(2)
| / \ |
| / \ |
| / \ |
(3) (4)
ii) Topological Sorting
Topological sorting for Directed Acyclic Graph (DAG) is a linear ordering of vertices such that for
every directed edge uv, vertex u comes before v in the ordering. Topological Sorting for a graph is not
possible if the graph is not a DAG.
For example, a topological sorting of the following graph is “5 4 2 3 1 0”. There can be more than one
topological sorting for a graph. For example, another topological sorting of the following graph is “4 5
2 3 1 0”. The first vertex in topological sorting is always a vertex with in-degree as 0 (a vertex with no
in-coming edges).
Topological Sorting vs Depth First Traversal (DFS):
In DFS, we print a vertex and then recursively call DFS for its adjacent vertices. In topological sorting,
we need to print a vertex before its adjacent vertices. For example, in the given graph, the vertex ‘5’
should be printed before vertex ‘0’, but unlike DFS, the vertex ‘4’ should also be printed before vertex
‘0’. So Topological sorting is different from DFS. For example, a DFS of the above graph is “5 2 3 1 0
4”, but it is not a topological sorting
Algorithm to find Topological Sorting:
We recommend to first see implementation of DFS here. We can modify DFS to find Topological
Sorting of a graph. In DFS, we start from a vertex, we first print it and then recursively call DFS for its
adjacent vertices. In topological sorting, we use a temporary stack. We don’t print the vertex
immediately, we first recursively call topological sorting for all its adjacent vertices, then push it to a
stack. Finally, print contents of stack. Note that a vertex is pushed to stack only when all of its
adjacent vertices (and their adjacent vertices and so on) are already in stack.
b) Find the minimum cost spanning tree using Kruskal's method for the following graph.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 29
11. Distinguish between
i) Files and records.
A record is the collection of fields that relate to a single entity. For example, we could have a
student record that includes fields for the student’s name, address, homeroom, date of birth, etc. A
product record could include fields for the serial number, description, cost price, quantity in stock, etc.
Example of a student record public class StudentRecord { private int idnumber; private String
lastName; private String firstName; private Date birthDate; private Date startingDate; private String
homeroom; .
A file is a collection of related records. For example, a student file might include all of the
records of students enrolled at a school. A police department might keep a file of criminal records,
which includes details about all known criminals. Files are stored on secondary storage devices such
as hard disks, CD-ROMs etc. Within a file, all records usually have the same structure. That is, every
record in the file contains the same fields. Only the data stored in the fields of different record will be
different.
iii) Input, output and input / output files.
ofstream: Stream class to write on files
ifstream: Stream class to read from files
fstream: Stream class to both read and write from/to files.
These classes are derived directly or indirectly from the classes istream and ostream. We have already
used objects whose types were these classes: cin is an object of class istream and cout is an object of
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 30
class ostream. Therefore, we have already been using classes that are related to our file streams. And
in fact, we can use our file streams the same way we are already used to use cin and cout, with the
only difference that we have to associate these streams with physical files. Let's see an example:
1
2
3
4
5
6
7
8
9
10
11
12
// basic file operations
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream myfile;
myfile.open ("example.txt");
myfile << "Writing this to a file.\n";
myfile.close();
return 0;
}
[file example.txt]
Writing this to a file.
This code creates a file called example.txt and inserts a sentence into it in the same way we are used to
do with cout, but using the file stream myfile instead.
But let's go step by step:
Open a file
The first operation generally performed on an object of one of these classes is to associate it to a real
file. This procedure is known as to open a file. An open file is represented within a program by
a stream (i.e., an object of one of these classes; in the previous example, this was myfile) and any
input or output operation performed on this stream object will be applied to the physical file associated
to it.
In order to open a file with a stream object we use its member function open:
open (filename, mode);
Where filename is a string representing the name of the file to be opened, and mode is an optional
parameter with a combination of the following flags:
ios::in Open for input operations.
ios::out Open for output operations.
ios::binary Open in binary mode.
ios::ate Set the initial position at the end of the file.
If this flag is not set, the initial position is the beginning of the file.
ios::app All output operations are performed at the end of the file, appending the content to the
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 31
current content of the file.
ios::trunc If the file is opened for output operations and it already existed, its previous content is
deleted and replaced by the new one.
ii) Sequential and Random access.
a sequential file is one where you start at the beginning and read each record IN SEQUENCE.
The same idea as playing a song on a Tape, or a movie on a VCR - in order to read record 12, you
MUST read records 1 through 11, in that precise order, first.
A random access file allows you to read ANY record, in ANY order, with having to have read any
other records first.
Think of it like houses along a street. You can go up to any house, without having to have gone up to
any other house, first.
With a Random Access file, you MUST know how long a record is, and the ALL MUST be tha same
length, so that you can easily go to the 12th record, without having to read the first 11.
In a Sequential fiel, each record can be of different length, because the length of arecord is not
important. In order to read the 12th record, you MUST read the first 11 records, no matter how long
each to those 11 records is.
the lof function returns the Length Of The file (LOF=LengthOfFile), in bytes.
12. a) Why B+ tree is considered a better structure than B-tree for implementation of an
indexed sequential.
B-tree is a tree data structure that keeps data sorted and allows searches, sequential access,
insertions, and deletions in logarithmic amortized time. The B-tree is a generalization of a binary
search tree in that a node can have more than two children.
B+ tree or B plus tree is a type of tree which represents sorted data in a way that allows for
efficient insertion, retrieval and removal of records, each of which is identified by a key. It is a
dynamic, multilevel index, with maximum and minimum bounds on the number of keys in each index
segment (usually called a "block" or "node").
In a B+ tree, in contrast to a B-tree, all records are stored at the leaf level of the tree; only keys
are stored in interior nodes.
Advantages of B+-trees:1) Any record can be fetched in equal number of disk accesses.2)
Range queries can be performed easily as leaves are linked up3) Height of the tree is less as only keys
are used for indexing4) Supports both random and sequential access
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 32
.Disadvantages of B+-trees:Insert and delete operations are complicatedRoot node becomes a
hotspot
OR
Key difference: In computers, the binary trees are tree data structures that store the data, and
allow the user to access, search, insert and delete the data at the algorithmic time. The difference
between a B and B+ tree is that, in a B-tree, both the keys and data in the internal/leaf nodes can be
stored, whereas in a B+ tree only the leaf nodes can be stored.
The Binary trees are balanced search trees, which are designed to work well on direct access
secondary storage devices such as the magnetic disks. Rudolf Bayer and Ed McCreight invented the
concept of a B-tree.
B Tree
b) Explain collision resolution and hash function.
HASH TABLE:
It is a Data structure where the data elements are stored(inserted), searched, deleted based on the keys
generated for each element, which is obtained from a hashing function. In a hashing system the keys
are stored in an array which is called the Hash Table. A perfectly implemented hash table would
always promise an average insert/delete/retrieval time of O(1).
HASHING FUNCTION:
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 33
A function which employs some algorithm to computes the key K for all the data elements in the
set U, such that the key K which is of a fixed size. The same key Kcan be used to map data to a hash
table and all the operations like insertion,deletion and searching should be possible. The values
returned by a hash function are also referred to as hash values, hash codes, hash sums, or hashes.
HASH COLLISION:
A situation when the resultant hashes for two or more data elements in the data set U, maps to the
same location in the has table, is called a hash collision. In such a situation two or more data elements
would qualify to be stored/mapped to the same location in the hash table.
==> However simple it may sound, it is practically never
possible to find a hashing function which computes unique
hashes for each element in the data set U. Further a
hash function should also be optimal w.r.t computing time
and should offer adequate ease of implementation.
Read the material about Birth Day Paradox in Wikipedia for
more info about the possibility of finding a perfect hash
and why it is nearly impossible.
HASH COLLISION RESOLUTION TECHNIQUES:
Open Hashing (Separate chaining)
Open Hashing, is a technique in which the data is not directly stored at the hash key index (k) of the
Hash table. Rather the data at the key index (k) in the hash table is a pointer to the head of the data
structure where the data is actually stored. In the most simple and common implementations the data
structure adopted for storing the element is a linked-list.
In this technique when a data needs to be searched, it might become necessary (worst case) to traverse
all the nodes in the linked list to retrieve the data.
Note that the order in which the data is stored in each of these linked lists (or other data structures) is
completely based on implementation requirements. Some of the popular criteria are insertion order,
frequency of access etc.
CLOSED HASHING (OPEN ADDRESSING)
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 34
In this technique a hash table with pre-identified size is considered. All items are stored in the hash
table itself. In addition to the data, each hash bucket also maintains the three states: EMPTY,
OCCUPIED, DELETED. While inserting, if a collision occurs, alternative cells are tried until an
empty bucket is found. For which one of the following technique is adopted.
1. Liner Probing (this is prone to clustering of data + Some other constrains. Refer Wiki)
2. Quadratic probing (for more detail refer Wiki)
3. Double hashing (in short in case of collision another hashing function is used with the key
value as an input to identify where in the open addressing scheme the data should actually be
stored.)
A comparative analysis of Closed Hashing vs Open Hashing
Open Addressing Closed Addressing
All elements would be
stored in the Hash table
itself. No additional data
structure is needed.
Additional Data
structure needs to be
used to accommodate
collision data.
In cases of collisions, a
unique hash key must be
obtained.
Simple and effective
approach to collision
resolution. Key may or
may not be unique.
Determining size of the
hash table, adequate
enough for storing all
the data is difficult.
Performance
deterioration of closed
addressing much slower
as compared to Open
addressing.
State needs be
maintained for the data
(additional work)
No state data needs to be
maintained (easier to
maintain)
Uses space efficiently Expensive on space
12) Explain difference between static bee table and dynamic pee table
The key thing in hashing is to find an easy to compute hash function. However, collisions cannot be
avoided. Here we discuss three strategies of dealing with collisions, linear probing, quadratic probing
and separate chaining.
Linear Probing Suppose that a key hashes into a position that is already occupied. The simplest strategy is to look for
the next available position to place the item. Suppose we have a set of hash codes consisting of {89,
18, 49, 58, 9} and we need to place them into a table of size 10. The following table demonstrates this
process.
TGPCET/CSE/Solution Set-S 16
DSPD Ms. Neha V. Mogre Page 35
Table Courtesy of Weiss Data Structures Book
The first collision occurs when 49 hashes to the same location with index 9. Since 89 occupies
the A[9], we need to place 49 to the next available position. Considering the array as circular, the next
available position is 0. That is (9+1) mod 10. So we place 49 in A[0]. Several more collisions occur in
this simple example and in each case we keep looking to find the next available location in the array to
place the element. Now if we need to find the element, say for example, 49, we first compute the hash
code (9), and look in A[9]. Since we do not find it there, we look inA[(9+1) % 10] = A[0], we find it
there and we are done. So what if we are looking for 79? First we compute hashcode of 79 = 9. We
probe in A[9], A[(9+1)%10]=A[0], A[(9+2)%10]=A[1], A[(9+3)%10]=A[2], A[(9+4)%10]=A[3] etc.
Since A[3] = null, we do know that 79 could not exists in the set.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 1
Tulsiramji Gaikwad-Patil College of Engineering and Technology
Department of Computer Science and Engineering
Semester : B.E. Fourth Semester
Subject : DSPD
Solution Set: Summer – 2017
1a) Explain the various sorting techniques. Give its time complexities.
Bubble Sort [Best: O(n), Worst:O(N^2)]
Starting on the left, compare adjacent items and keep “bubbling” the larger one to the right (it’s in
its final place). Bubble sort the remaining N -1 items.
Though “simple” I found bubble sort nontrivial. In general, sorts where you iterate
backwards (decreasing some index) were counter-intuitive for me. With bubble-sort, either
you bubble items “forward” (left-to-right) and move the endpoint backwards (decreasing),
or bubble items “backward” (right-to-left) and increase the left endpoint. Either way, some
index is decreasing.
You also need to keep track of the next-to-last endpoint, so you don’t swap with a non-
existent item.
Selection Sort [Best/Worst: O(N^2)]
Scan all items and find the smallest. Swap it into position as the first item. Repeat the selection sort
on the remaining N-1 items.
I found this the most intuitive and easiest to implement — you always iterate forward (i
from 0 to N-1), and swap with the smallest element (always i).
Insertion Sort [Best: O(N), Worst:O(N^2)]
Start with a sorted list of 1 element on the left, and N-1 unsorted items on the right. Take the first
unsorted item (element #2) and insert it into the sorted list, moving elements as necessary. We now
have a sorted list of size 2, and N -2 unsorted elements. Repeat for all elements.
Like bubble sort, I found this counter-intuitive because you step “backwards”
This is a little like bubble sort for moving items, except when you encounter an item smaller
than you, you stop. If the data is reverse-sorted, each item must travel to the head of the list,
and this becomes bubble-sort.
There are various ways to move the item leftwards — you can do a swap on each iteration,
or copy each item over its neighbor
Radix sort [Best/Avg/Worst: O(N)]
Get a series of numbers, and sort them one digit at a time (moving all the 1000’s ahead of the
2000’s, etc.). Repeat the sorting on each set of digits.
Radix sort uses counting sort for efficient O(N) sorting of the digits (k = 0…9)
Actually, radix sort goes from least significant digit (1’s digit) to most significant, for
reasons I’ll explain later (see CLRS book)
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 2
Radix & counting sort are fast, but require structured data, external memory and do not have
the caching benefits of quicksort.
1 b) Write an algorithm of Bubble sort.
Bubble Sort
The algorithm works by comparing each item in the list with the item next to it, and swapping them
if required. In other words, the largest element has bubbled to the top of the array. The algorithm
repeats this process until it makes a pass all the way through the list without swapping any items.
void bubbleSort(int ar[])
{
for (int i = (ar.length - 1); i >= 0; i--)
{
for (int j = 1; j ≤ i; j++)
{
if (ar[j-1] > ar[j])
{
int temp = ar[j-1];
ar[j-1] = ar[j];
ar[j] = temp;
} } } }
Example. Here is one step of the algorithm. The largest element - 7 - is bubbled to the top:
7, 5, 2, 4, 3, 9
5, 7, 2, 4, 3, 9
5, 2, 7, 4, 3, 9
5, 2, 4, 7, 3, 9
5, 2, 4, 3, 7, 9
5, 2, 4, 3, 7, 9
The worst-case runtime complexity is O(n2). See explanation below
2 a) Write a program to implement Binary Search
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 3
#include <stdio.h>
int main()
{
int c, first, last, middle, n, search, array[100];
printf("Enter number of elements\n");
scanf("%d",&n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d",&array[c]);
printf("Enter value to find\n");
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while (first <= last) {
if (array[middle] < search)
first = middle + 1;
else if (array[middle] == search) {
printf("%d found at location %d.\n", search, middle+1);
break;
}
else
last = middle - 1;
middle = (first + last)/2;
}
if (first > last)
printf("Not found! %d is not present in the list.\n", search);
return 0;
}
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 4
2b) Explain the following terms :––
i)Sparse Matrix.
What is Sparse Matrix?
In computer programming, a matrix can be defined with a 2-dimensional array. Any array with 'm'
columns and 'n' rows represents a mXn matrix. There may be a situation in which a matrix contains
more number of ZERO values than NON-ZERO values. Such matrix is known as sparse matrix.
Sparse matrix is a matrix which contains very few non-zero elements.
When a sparse matrix is represented with 2-dimensional array, we waste lot of space to represent
that matrix. For example, consider a matrix of size 100 X 100 containing only 10 non-zero
elements. In this matrix, only 10 spaces are filled with non-zero values and remaining spaces of
matrix are filled with zero. That means, totally we allocate 100 X 100 X 2 = 20000 bytes of space to
store this integer matrix. And to access these 10 non-zero elements we have to make scanning for
10000 times.
Sparse Matrix Representations
A sparse matrix can be represented by using TWO representations, those are as follows...
1. Triplet Representation
2. Linked Representation
Triplet Representation
In this representation, we consider only non-zero values along with their row and column index
values. In this representation, the 0th row stores total rows, total columns and total non-zero values
in the matrix.
For example, consider a matrix of size 5 X 6 containing 6 number of non-zero values. This matrix
can be represented as shown in the image...
In above example matrix, there are only 6 non-zero elements ( those are 9, 8, 4, 2, 5 & 2) and
matrix size is 5 X 6. We represent this matrix as shown in the above image. Here the first row in the
right side table is filled with values 5, 6 & 6 which indicates that it is a sparse matrix with 5 rows, 6
columns & 6 non-zero values. Second row is filled with 0, 4, & 9 which indicates the value in the
matrix at 0th row, 4th column is 9. In the same way the remaining non-zero values also follows the
similar pattern.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 5
Linked Representation
In linked representation, we use linked list data structure to represent a sparse matrix. In this linked
list, we use two different nodes namely header node and element node. Header node consists of
three fields and element node consists of five fields as shown in the image...
Consider the above same sparse matrix used in the Triplet representation. This sparse matrix can be
represented using linked representation as shown in the below image...
In above representation, H0, H1,...,H5 indicates the header nodes which are used to represent
indexes. Remaining nodes are used to represent non-zero elements in the matrix, except the very
first node which is used to represent abstract information of the sparse matrix (i.e., It is a matrix of
5 X 6 with 6 non-zero elements).
In this representation, in each row and column, the last node right field points to it's respective
header node.
2) What is Time complexity?
Every algorithm requires some amount of computer time to execute its instruction to perform the
task. This computer time required is called time complexity.
Time complexity of an algorithm can be defined as follows...
The time complexity of an algorithm is the total amount of time required by an algorithm to
complete its execution.
Generally, running time of an algorithm depends upon the following...
1. Whether it is running on Single processor machine or Multi processor machine.
2. Whether it is a 32 bit machine or 64 bit machine
3. Read and Write speed of the machine.
4. The time it takes to perform Arithmetic operations, logical operations, return value and
assignment operations etc.,
5. Input data
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 6
NOTE
☀ When we calculate time complexity of an algorithm, we consider only input data and ignore the
remaining things, as they are machine dependent. We check only, how our program is behaving for
the different input values to perform all the operations like Arithmetic, Logical, Return value and
Assignment etc.,
Calculating Time Complexity of an algorithm based on the system configuration is a very difficult
task because, the configuration changes from one system to another system. To solve this problem,
we must assume a model machine with specific configuration. So that, we can able to calculate
generalized time complexity according to that model machine.
To calculate time complexity of an algorithm, we need to define a model machine. Let us assume a
machine with following configuration...
1. Single processor machine
2. 32 bit Operating System machine
3. It performs sequential execution
4. It requires 1 unit of time for Arithmetic and Logical operations
5. It requires 1 unit of time for Assignment and Return value
6. It requires 1 unit of time for Read and Write operations
Now, we calculate the time complexity of following example code by using the above defined
model machine...
Example 1
Consider the following piece of code...
int sum(int a, int b)
{
return a+b;
}
In above sample code, it requires 1 unit of time to calculate a+b and 1 unit of time to return the
value. That means, totally it takes 2 units of time to complete its execution. And it does not change
based on the input values of a and b. That means for all input values, it requires same amount of
time i.e. 2 units.
If any program requires fixed amount of time for all input values then its time complexity is said to
be Constant Time Complexity.
For the above code, time complexity can be calculated as follows...
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 7
In above calculation
Cost is the amount of computer time required for a single operation in each line.
Repeatation is the amount of computer time required by each operation for all its repeatations.
Total is the amount of computer time required by each operation to execute.
So above code requires '4n+4' Units of computer time to complete the task. Here the exact time is
not fixed. And it changes based on the n value. If we increase the n value then the time required
also increases linearly.
Totally it takes '4n+4' units of time to complete its execution and it is Linear Time Complexity.
If the amount of time required by an algorithm is increased with the increase of input value then
that time complexity is said to be Linear Time Complexity
3) What is Space complexity?
When we design an algorithm to solve a problem, it needs some computer memory to complete its
execution. For any algorithm, memory is required for the following purposes...
1. Memory required to store program instructions
2. Memory required to store constant values
3. Memory required to store variable values
4. And for few other things
Space complexity of an algorithm can be defined as follows...
Total amount of computer memory required by an algorithm to complete its execution is called as
space complexity of that algorithm
Generally, when a program is under execution it uses the computer memory for THREE reasons.
They are as follows...
1. Instruction Space: It is the amount of memory used to store compiled version of
instructions.
2. Environmental Stack: It is the amount of memory used to store information of partially
executed functions at the time of function call.
3. Data Space: It is the amount of memory used to store all the variables and constants.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 8
NOTE
☀ When we want to perform analysis of an algorithm based on its Space complexity, we consider
only Data Space and ignore Instruction Space as well as Environmental Stack.
That means we calculate only the memory required to store Variables, Constants, Structures, etc.,
To calculate the space complexity, we must know the memory required to store different datatype
values (according to the compiler). For example, the C Programming Language compiler requires
the following...
1. 2 bytes to store Integer value,
2. 4 bytes to store Floating Point value,
3. 1 byte to store Character value,
4. 6 (OR) 8 bytes to store double value
Example 1
Consider the following piece of code...
int square(int a)
{
return a*a;
}
In above piece of code, it requires 2 bytes of memory to store variable 'a' and another 2 bytes of
memory is used for return value.
That means, totally it requires 4 bytes of memory to complete its execution. And this 4 bytes
of memory is fixed for any input value of 'a'. This space complexity is said to be Constant
Space Complexity.
If any algorithm requires a fixed amount of space for all input values then that space complexity is
said to be Constant Space Complexity
Example 2
Consider the following piece of code...
int sum(int A[], int n)
{
int sum = 0, i;
for(i = 0; i < n; i++)
sum = sum + A[i];
return sum;
}
In above piece of code it requires
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 9
'n*2' bytes of memory to store array variable 'a[]'
2 bytes of memory for integer parameter 'n'
4 bytes of memory for local integer variables 'sum' and 'i' (2 bytes each)
2 bytes of memory for return value.
That means, totally it requires '2n+8' bytes of memory to complete its execution. Here, the
amount of memory depends on the input value of 'n'. This space complexity is said to be
Linear Space Complexity.
If the amount of space required by an algorithm is increased with the increase of input value, then
that space complexity is said to be Linear Space Complexity
3a) Write a Menu Driven Program for various operations of singly linked list.
#include<stdio.h>
#include<conio.h>
#include<process.h>
struct node
{
int data;
struct node *next;
}*start=NULL,*q,*t;
int main()
{
int ch;
void insert_beg();
void insert_end();
int insert_pos();
void display();
void delete_beg();
void delete_end();
int delete_pos();
while(1)
{
printf("\n\n---- Singly Linked List(SLL) Menu ----");
printf("\n1.Insert\n2.Display\n3.Delete\n4.Exit\n\n");
printf("Enter your choice(1-4):");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\n---- Insert Menu ----");
printf("\n1.Insert at beginning\n2.Insert at end\n3.Insert at specified position\n4.Exit");
printf("\n\nEnter your choice(1-4):");
scanf("%d",&ch);
switch(ch)
{
case 1: insert_beg();
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 10
break;
case 2: insert_end();
break;
case 3: insert_pos();
break;
case 4: exit(0);
default: printf("Wrong Choice!!");
}
break;
case 2: display();
break;
case 3: printf("\n---- Delete Menu ----");
printf("\n1.Delete from beginning\n2.Delete from end\n3.Delete from specified
position\n4.Exit");
printf("\n\nEnter your choice(1-4):");
scanf("%d",&ch);
switch(ch)
{
case 1: delete_beg();
break;
case 2: delete_end();
break;
case 3: delete_pos();
break;
case 4: exit(0);
default: printf("Wrong Choice!!");
}
break;
case 4: exit(0);
default: printf("Wrong Choice!!");
}
}
return 0;
}
void insert_beg()
{
int num;
t=(struct node*)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&num);
t->data=num;
if(start==NULL) //If list is empty
{
t->next=NULL;
start=t;
}
else
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 11
{
t->next=start;
start=t;
}
}
void insert_end()
{
int num;
t=(struct node*)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&num);
t->data=num;
t->next=NULL;
if(start==NULL) //If list is empty
{
start=t;
}
else
{
q=start;
while(q->next!=NULL)
q=q->next;
q->next=t;
}
}
int insert_pos()
{
int pos,i,num;
if(start==NULL)
{
printf("List is empty!!");
return 0;
}
t=(struct node*)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&num);
printf("Enter position to insert:");
scanf("%d",&pos);
t->data=num;
q=start;
for(i=1;i<pos-1;pos++)
{
if(q->next==NULL)
{
printf("There are less elements!!");
return 0;
}
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 12
q=q->next;
}
t->next=q->next;
q->next=t;
return 0;
}
void display()
{
if(start==NULL)
{
printf("List is empty!!");
}
else
{
q=start;
printf("The linked list is:\n");
while(q!=NULL)
{
printf("%d->",q->data);
q=q->next;
}
}
}
void delete_beg()
{
if(start==NULL)
{
printf("The list is empty!!");
}
else
{
q=start;
start=start->next;
printf("Deleted element is %d",q->data);
free(q);
}
}
void delete_end()
{
if(start==NULL)
{
printf("The list is empty!!");
}
else
{
q=start;
while(q->next->next!=NULL)
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 13
q=q->next;
t=q->next;
q->next=NULL;
printf("Deleted element is %d",t->data);
free(t);
}
}
int delete_pos()
{
int pos,i;
if(start==NULL)
{
printf("List is empty!!");
return 0;
}
printf("Enter position to delete:");
scanf("%d",&pos);
for(i=1;i<pos-1;pos++)
{
if(q->next==NULL)
{
printf("There are less elements!!");
return 0;
}
q=q->next;
}
t=q->next;
q->next=t->next;
printf("Deleted element is %d",t->data);
free(t);
return 0;
}
Output —- Singly Linked List(SLL) Menu —-
1.Insert
2.Display
3.Delete
4.ExitEnter your choice(1-4):1—- Insert Menu —-
1.Insert at beginning
2.Insert at end
3.Insert at specified position
4.Exit
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 14
Enter your choice(1-4):1
Enter data:4
—- Singly Linked List(SLL) Menu —-
1.Insert
2.Display
3.Delete
4.Exit
Enter your choice(1-4):2
The linked list is:
4->
—- Singly Linked List(SLL) Menu —-
1.Insert
2.Display
3.Delete
4.Exit
Enter your choice(1-4):4
3 b) Give suitable representation for polynomials and write an algorithm to add two
polynomials.
Program to add two polynomials
Given two polynomials represented by two arrays, write a function that adds given two
polynomials.
Example:
Input: A[] = {5, 0, 10, 6}
B[] = {1, 2, 4}
Output: sum[] = {5, 10, 30, 26, 52, 24}
The first input array represents "5 + 0x^1 + 10x^2 + 6x^3"
The second array represents "1 + 2x^1 + 4x^2"
And Output is "6 + 2x^1 + 14x^2 + 6x^3"
Addition is simpler than multiplication of polynomials. We initialize result as one of the two
polynomials, then we traverse the other polynomial and add all terms to the result.
add(A[0..m-1], B[0..n01])
1) Create a sum array sum[] of size equal to maximum of 'm' and 'n'
2) Copy A[] to sum[].
3) Travers array B[] and do following for every element B[i]
sum[i] = sum[i] + B[i]
4) Return sum[].
The following is C++ implementation of above algorithm.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 15
// Simple C++ program to add two polynomials
#include <iostream>
using namespace std;
// A utility function to return maximum of two integers
int max(int m, int n) { return (m > n)? m: n; }
// A[] represents coefficients of first polynomial
// B[] represents coefficients of second polynomial
// m and n are sizes of A[] and B[] respectively
int *add(int A[], int B[], int m, int n)
{
int size = max(m, n);
int *sum = new int[size];
// Initialize the porduct polynomial
for (int i = 0; i<m; i++)
sum[i] = A[i];
// Take ever term of first polynomial
for (int i=0; i<n; i++)
sum[i] += B[i];
return sum;
}
// A utility function to print a polynomial
void printPoly(int poly[], int n)
{
for (int i=0; i<n; i++)
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 16
{
cout << poly[i];
if (i != 0)
cout << "x^" << i ;
if (i != n-1)
cout << " + ";
}
}
// Driver program to test above functions
int main()
{
// The following array represents polynomial 5 + 10x^2 + 6x^3
int A[] = {5, 0, 10, 6};
// The following array represents polynomial 1 + 2x + 4x^2
int B[] = {1, 2, 4};
int m = sizeof(A)/sizeof(A[0]);
int n = sizeof(B)/sizeof(B[0]);
cout << "First polynomial is \n";
printPoly(A, m);
cout << "\nSecond polynomial is \n";
printPoly(B, n);
int *sum = add(A, B, m, n);
int size = max(m, n);
cout << "\nsumuct polynomial is \n";
printPoly(sum, size);
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 17
return 0;
}
Output:
First polynomial is
5 + 0x^1 + 10x^2 + 6x^3
Second polynomial is
1 + 2x^1 + 4x^2
Sum polynomial is
6 + 2x^1 + 14x^2 + 6x^3
Time complexity of the above algorithm and program is O(m+n) where m and n are orders of two
given polynomials.
4) Write a function to :––
(i) Insert a node at end in doubly linked list
Insertion At Last in doubly linked list
Algorithm
1. InsertAtEndDll(info,prev,next,start,end)
2. 1.create a new node and address in assigned to ptr.
3. 2.check[overflow] if(ptr=NULL)
4. write:overflow and exit
5. 3.set Info[ptr]=item;
6. 4.if(start=NULL)
7. set prev[ptr] = next[ptr] = NULL
8. set start = end = ptr
9. else
10. set prev[ptr] = end
11. next[end] = ptr
12. set ptr[next] = NULL
13. set end = ptr
14. [end if]
15. 5.Exit.
b)Delete a node from a specific position from doubly linked list.
Algorithm to delete node from any position of a doubly linked list
Algorithm to delete node from any position %% Input : head {Pointer to the first node of the list}
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 18
last {Pointer to the last node of the list}
N {Position to be deleted from list}
Begin:
current ← head;
For i ← 1 to N and current != NULL do
current ← current.next;
End for If (N == 1) then
deleteFromBeginning()
End if Else if (current == last) then
deleteFromEnd()
End if Else if (current != NULL) then
current.prev.next ← current.next
If (current.next != NULL) then
current.next.prev ← current.prev;
End if
unalloc (current)
write ('Node deleted successfully from ', N, ' position')
End if
Else then
write ('Invalid position')
End if
End
4b) What is static memory allocation and dynamic memory allocation ? What are the
functions used for dynamic memory allocation in ''C'' ? Give examples.
static memory allocation and dynamic memory allocation:-
Static Memory Allocation: Memory is allocated for the declared variable by the compiler. The
address can be obtained by using ‘address of’ operator and can be assigned to a pointer. The
memory is allocated during compile time. Since most of the declared variables have static memory,
this kind of assigning the address of a variable to a pointer is known as static memory allocation.
Dynamic Memory Allocation: Allocation of memory at the time of execution (run time) is known
as dynamic memory allocation. The functions calloc() and malloc() support allocating of dynamic
memory. Dynamic allocation of memory space is done by using these functions when value is
returned by functions and assigned to pointer variables.
In C, the exact size of array is unknown until compile time, i.e., the time when a compiler compiles
your code into a computer understandable language. So, sometimes the size of the array can be
insufficient or more than required.
Dynamic memory allocation allows your program to obtain more memory space while running, or
to release it if it's not required.
In simple terms, Dynamic memory allocation allows you to manually handle memory space for
your program.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 19
Although, C language inherently does not have any technique to allocate memory dynamically,
there are 4 library functions under "stdlib.h" for dynamic memory allocation.
Function Use of Function
malloc() Allocates requested size of bytes and returns a pointer first byte of allocated space
calloc()
Allocates space for an array elements, initializes to zero and then returns a pointer to
memory
free() deallocate the previously allocated space
realloc() Change the size of previously allocated space
C malloc()
The name malloc stands for "memory allocation".
The function malloc() reserves a block of memory of specified size and return a pointer of type void
which can be casted into pointer of any form.
Syntax of malloc()
ptr = (cast-type*) malloc(byte-size)
Here, ptr is pointer of cast-type. The malloc() function returns a pointer to an area of memory with
size of byte size. If the space is insufficient, allocation fails and returns NULL pointer.
ptr = (int*) malloc(100 * sizeof(int));
This statement will allocate either 200 or 400 according to size of int 2 or 4 bytes respectively and
the pointer points to the address of first byte of memory.
C calloc()
The name calloc stands for "contiguous allocation".
The only difference between malloc() and calloc() is that, malloc() allocates single block of
memory whereas calloc() allocates multiple blocks of memory each of same size and sets all bytes
to zero.
Syntax of calloc()
ptr = (cast-type*)calloc(n, element-size);
This statement will allocate contiguous space in memory for an array of n elements. For example:
ptr = (float*) calloc(25, sizeof(float));
This statement allocates contiguous space in memory for an array of 25 elements each of size of
float, i.e, 4 bytes.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 20
C free()
Dynamically allocated memory created with either calloc() or malloc() doesn't get freed on its own.
You must explicitly use free() to release the space.
syntax of free()
free(ptr);
This statement frees the space allocated in the memory pointed by ptr.
5a) Write an algorithm which convert infix expression into postfix from using stack and give
steps of each.
nfix to Postfix Conversion
Procedure for Postfix Conversion
1. Scan the Infix string from left to right.
2. Initialize an empty stack.
3. If the scanned character is an operand, add it to the Postfix string.
4. If the scanned character is an operator and if the stack is empty push the character to stack.
5. If the scanned character is an Operator and the stack is not empty, compare the precedence of
the character with the element on top of the stack.
6.
If top Stack has higher precedence over the scanned character pop the stack else push the
scanned character to stack. Repeat this step until the stack is not empty and top Stack has
precedence over the character.
7. Repeat 4 and 5 steps till all the characters are scanned.
8. After all characters are scanned, we have to add any character that the stack may have to the
Postfix string.
9. If stack is not empty add top Stack to Postfix string and Pop the stack.
10. Repeat this step as long as stack is not empty.
Algorithm for Postfix Conversion
1. S:stack
2. while(more tokens)
3. x<=next token
4. if(x == operand)
5. print x
6. else
7. while(precedence(x)<=precedence(top(s)))
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 21
8. print(pop(s))
9. push(s,x)
10. while(! empty (s))
11. print(pop(s))
Conversion To Postfix
EXAMPLE:
A+(B*C-(D/E-F)*G)*H
Stack Input Output
Empty A+(B*C-(D/E-F)*G)*H -
Empty +(B*C-(D/E-F)*G)*H A
+ (B*C-(D/E-F)*G)*H A
+( B*C-(D/E-F)*G)*H A
+( *C-(D/E-F)*G)*H AB
+(* C-(D/E-F)*G)*H AB
+(* -(D/E-F)*G)*H ABC
+(- (D/E-F)*G)*H ABC*
+(-( D/E-F)*G)*H ABC*
+(-( /E-F)*G)*H ABC*D
+(-(/ E-F)*G)*H ABC*D
+(-(/ -F)*G)*H ABC*DE
+(-(- F)*G)*H ABC*DE/
+(-(- F)*G)*H ABC*DE/
+(-(- )*G)*H ABC*DE/F
+(- *G)*H ABC*DE/F-
+(-* G)*H ABC*DE/F-
+(-* )*H ABC*DE/F-G
+ *H ABC*DE/F-G*-
+* H ABC*DE/F-G*-
+* End ABC*DE/F-G*-H
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 22
Empty End ABC*DE/F-G*-H*+
Infix to postfix implementation in c
1. #include <stdio.h>
2. #include <conio.h>
3. #include <ctype.h>
4. #define SIZE 50
5. char s[SIZE];
6. int top=-1;
7. push(char elem)
8. {
9. s[++top]=elem;
10. }
11.
12. char pop()
13. {
14. return(s[top--]);
15. }
16.
17. int pr(char elem)
18. {
19. switch(elem)
20. {
21. case '#': return 0;
22. case '(': return 1;
23. case '+':
24. case '-': return 2;
25. case '*':
26. case '/': return 3;
27. }
28. }
29.
30. void main()
31. {
32. char infx[50],pofx[50],ch,elem;
33. int i=0,k=0;
34. clrscr();
35. printf("\n\nRead the Infix Expression ? ");
36. scanf("%s",infx);
37. push('#');
38. while( (ch=infx[i++]) != '\0')
39. {
40. if( ch == '(') push(ch);
41. else
42. if(isalnum(ch)) pofx[k++]=ch;
43. else
44. if( ch == ')')
45. {
46. while( s[top] != '(')
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 23
47. pofx[k++]=pop();
48. elem=pop();
49. }
50. else
51. {
52. while( pr(s[top]) >= pr(ch) )
53. pofx[k++]=pop();
54. push(ch);
55. }
56. }
57. while( s[top] != '#')
58. pofx[k++]=pop();
59. pofx[k]='\0';
60. printf("\n\nGiven Infix Expn: %s Postfix Expn: %s\n",infx,pofx);
61. getch();
62. }
Output
5 a)Briefly explain :––
i) Deque.(Refer 2016 paper)
ii) Priority Queues.
Priority Queue is more specialized data structure than Queue. Like ordinary queue, priority
queue has same method but with a major difference. In Priority queue items are ordered by key
value so that item with the lowest value of key is at front and item with the highest value of key is
at rear or vice versa. So we're assigned priority to item based on its key value. Lower the value,
higher the priority. Following are the principal methods of a Priority Queue.
Basic Operations
insert / enqueue − add an item to the rear of the queue.
remove / dequeue − remove an item from the front of the queue.
Priority Queue Representation
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 24
We're going to implement Queue using array in this article. There is few more operations supported
by queue which are following.
Peek − get the element at front of the queue.
isFull − check if queue is full.
isEmpty − check if queue is empty.
Insert / Enqueue Operation
Whenever an element is inserted into queue, priority queue inserts the item according to its order.
Here we're assuming that data with high value has low priority.
6a) What do you mean by circular queues ? Give the array implementation of it and write an
algorithm for insertion and deletion of elements from circular queues.
Circular Queue
In a normal Queue Data Structure, we can insert elements until queue becomes full. But once if
queue becomes full, we can not insert the next element until all the elements are deleted from the
queue. For example consider the queue below...
After inserting all the elements into the queue.
Now consider the following situation after deleting three elements from the queue...
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 25
This situation also says that Queue is Full and we can not insert the new element because, 'rear' is
still at last position. In above situation, even though we have empty positions in the queue we can
not make use of them to insert new element. This is the major problem in normal queue data
structure. To overcome this problem we use circular queue data structure.
Implementation of Circular Queue
To implement a circular queue data structure using array, we first perform the following steps
before we implement actual operations.
Step 1: Include all the header files which are used in the program and define a constant
'SIZE' with specific value.
Step 2: Declare all user defined functions used in circular queue implementation.
Step 3: Create a one dimensional array with above defined SIZE (int cQueue[SIZE])
Step 4: Define two integer variables 'front' and 'rear' and initialize both with '-1'. (int
front = -1, rear = -1)
Step 5: Implement main method by displaying menu of operations list and make suitable
function calls to perform operation selected by the user on circular queue.
enQueue(value) - Inserting value into the Circular Queue
In a circular queue, enQueue() is a function which is used to insert an element into the circular
queue. In a circular queue, the new element is always inserted at rear position. The enQueue()
function takes one integer value as parameter and inserts that value into the circular queue. We can
use the following steps to insert an element into the circular queue...
Step 1: Check whether queue is FULL. ((rear == SIZE-1 && front == 0) || (front ==
rear+1))
Step 2: If it is FULL, then display "Queue is FULL!!! Insertion is not possible!!!" and
terminate the function.
Step 3: If it is NOT FULL, then check rear == SIZE - 1 && front != 0 if it is TRUE,
then set rear = -1.
Step 4: Increment rear value by one (rear++), set queue[rear] = value and check 'front ==
-1' if it is TRUE, then set front = 0.
deQueue() - Deleting a value from the Circular Queue
In a circular queue, deQueue() is a function used to delete an element from the circular queue. In a
circular queue, the element is always deleted from front position. The deQueue() function doesn't
take any value as parameter. We can use the following steps to delete an element from the circular
queue...
Step 1: Check whether queue is EMPTY. (front == -1 && rear == -1)
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 26
Step 2: If it is EMPTY, then display "Queue is EMPTY!!! Deletion is not possible!!!"
and terminate the function.
Step 3: If it is NOT EMPTY, then display queue[front] as deleted element and increment
the front value by one (front ++). Then check whether front == SIZE, if it is TRUE, then
set front = 0. Then check whether both front - 1 and rear are equal (front -1 == rear), if it
TRUE, then set both front and rear to '-1' (front = rear = -1).
display() - Displays the elements of a Circular Queue
We can use the following steps to display the elements of a circular queue...
Step 1: Check whether queue is EMPTY. (front == -1)
Step 2: If it is EMPTY, then display "Queue is EMPTY!!!" and terminate the function.
Step 3: If it is NOT EMPTY, then define an integer variable 'i' and set 'i = front'.
Step 4: Check whether 'front <= rear', if it is TRUE, then display 'queue[i]' value and
increment 'i' value by one (i++). Repeat the same until 'i <= rear' becomes FALSE.
Step 5: If 'front <= rear' is FALSE, then display 'queue[i]' value and increment 'i' value by
one (i++). Repeat the same until'i <= SIZE - 1' becomes FALSE.
Step 6: Set i to 0.
Step 7: Again display 'cQueue[i]' value and increment i value by one (i++). Repeat the
same until 'i <= rear' becomes FALSE.
Program to implement Queue using Array
#include<stdio.h>
#include<conio.h>
#define SIZE 5
void enQueue(int);
void deQueue();
void display();
int cQueue[SIZE], front = -1, rear = -1;
void main()
{
int choice, value;
clrscr();
while(1){
printf("\n****** MENU ******\n");
printf("1. Insert\n2. Delete\n3. Display\n4. Exit\n");
printf("Enter your choice: ");
scanf("%d",&choice);
switch(choice){
case 1: printf("\nEnter the value to be insert: ");
scanf("%d",&value);
enQueue(value);
break;
case 2: deQueue();
break;
case 3: display();
break;
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 27
case 4: exit(0);
default: printf("\nPlease select the correct choice!!!\n");
}
}
}
void enQueue(int value)
{
if((front == 0 && rear == SIZE - 1) || (front == rear+1))
printf("\nCircular Queue is Full! Insertion not possible!!!\n");
else{
if(rear == SIZE-1 && front != 0)
rear = -1;
cQueue[++rear] = value;
printf("\nInsertion Success!!!\n");
if(front == -1)
front = 0;
}
}
void deQueue()
{
if(front == -1 && rear == -1)
printf("\nCircular Queue is Empty! Deletion is not possible!!!\n");
else{
printf("\nDeleted element : %d\n",cQueue[front++]);
if(front == SIZE)
front = 0;
if(front-1 == rear)
front = rear = -1;
}
}
void display()
{
if(front == -1)
printf("\nCircular Queue is Empty!!!\n");
else{
int i = front;
printf("\nCircular Queue Elements are : \n");
if(front <= rear){
while(i <= rear)
printf("%d\t",cQueue[i++]);
}
else{
while(i <= SIZE - 1)
printf("%d\t", cQueue[i++]);
i = 0;
while(i <= rear)
printf("%d\t",cQueue[i++]);
}
}
}
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 28
Output
7) Explain the terms :––
i) Polish Notations
The name comes from the Polish mathematician/logician Lukasiewicz, who introduced it. Three
types:
Infix form
Prefix form
Postfix form
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 29
Infix form
Is exactly the fully parenthesized notation we have just introduced. Let me remind you once again
the Recursive definition
infix-expression := (infix-expression operand infix-expression)
infix-expression := atom
Examples
(3 * 7)
((1 + 3) * 2)
((1 + 3) * ( 2 - 3))
Main Feature: the binary operator is between the two operands.
Question: what if we do not put all the parentheses? Then there are ambiguities on how to interpret
an expression: is 1+2*3 the same as (1+2)*3 or the same as 1+(2*3)? The precedence of operators
solves this problem.
Prefix form
Main Feature: the operator preceeds the two operands.
Recursive definition of fully parenthesized version:
prefix-expression := (operand prefix-expression prefix-expression)
prefix-expression := atom
Recursive definition of classic version, without parentheses (we do not need them, because there is
no longer any ambiguity on how to match the operands to the operators):
prefix-expression := operand prefix-expression prefix-expression
prefix-expression := atom
Examples
(* 3 7) or simply * 3 7
(* ( + 1 3) 2) or simply * + 1 3 2
( * ( + 1 3) ( - 2 3)) or simply * + 1 3 - 2 3
Postfix form
Main Feature: the operator is after the two operands. Recursive definition
postfix-expression := (operand postfix-expression postfix-expression)
postfix-expression := atom
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 30
Recursive definition of classic version, without parentheses (we do not need them, because there is
no longer any ambiguity on how to match the operands to the operators):
postfix-expression := operand postfix-expression postfix-expression
postfix-expression := atom
Examples
(3 7 *) or simply 3 7 *
((1 3 + ) 2 *) or simply 1 3 + 2 *
((1 3 +) ( 2 3 -) * ) or simply 1 3 + 2 3 - *
b) Push and POP Algorithm.
A stack is an Abstract Data Type (ADT), commonly used in most programming languages. It is
named stack as it behaves like a real-world stack, for example – a deck of cards or a pile of plates,
etc.A real-world stack allows operations at one end only. For example, we can place or remove a
card or plate from the top of the stack only. Likewise, Stack ADT allows all data operations at one
end only. At any given time, we can only access the top element of a stack.
This feature makes it LIFO data structure. LIFO stands for Last-in-first-out. Here, the element
which is placed (inserted or added) last, is accessed first. In stack terminology, insertion operation
is called PUSH operation and removal operation is called POP operation.
Stack Representation
The following diagram depicts a stack and its operations −
A stack can be implemented by means of Array, Structure, Pointer, and Linked List. Stack can
either be a fixed size one or it may have a sense of dynamic resizing. Here, we are going to
implement stack using arrays, which makes it a fixed size stack implementation.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 31
Basic Operations
Stack operations may involve initializing the stack, using it and then de-initializing it. Apart from
these basic stuffs, a stack is used for the following two primary operations −
push() − Pushing (storing) an element on the stack.
pop() − Removing (accessing) an element from the stack.
When data is PUSHed onto stack.
To use a stack efficiently, we need to check the status of stack as well. For the same purpose, the
following functionality is added to stacks −
peek() − get the top data element of the stack, without removing it.
isFull() − check if stack is full.
isEmpty() − check if stack is empty.
At all times, we maintain a pointer to the last PUSHed data on the stack. As this pointer always
represents the top of the stack, hence named top. The top pointer provides top value of the stack
without actually removing it.
First we should learn about procedures to support stack functions −
peek()
Algorithm of peek() function −
begin procedure peek
return stack[top]
end procedure
Implementation of peek() function in C programming language −
Example
int peek() {
return stack[top];
}
isfull()
Algorithm of isfull() function −
begin procedure isfull
if top equals to MAXSIZE
return true
else
return false
endif
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 32
end procedure
Implementation of isfull() function in C programming language −
Example
bool isfull() {
if(top == MAXSIZE)
return true;
else
return false;
}
isempty()
Algorithm of isempty() function −
begin procedure isempty
if top less than 1
return true
else
return false
endif
end procedure
Implementation of isempty() function in C programming language is slightly different. We initialize
top at -1, as the index in array starts from 0. So we check if the top is below zero or -1 to determine
if the stack is empty. Here's the code −
Example
bool isempty() {
if(top == -1)
return true;
else
return false;
}
Push Operation
The process of putting a new data element onto stack is known as a Push Operation. Push operation
involves a series of steps −
Step 1 − Checks if the stack is full.
Step 2 − If the stack is full, produces an error and exit.
Step 3 − If the stack is not full, increments top to point next empty space.
Step 4 − Adds data element to the stack location, where top is pointing.
Step 5 − Returns success.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 33
If the linked list is used to implement the stack, then in step 3, we need to allocate space
dynamically.
Algorithm for PUSH Operation
A simple algorithm for Push operation can be derived as follows −
begin procedure push: stack, data
if stack is full
return null
endif
top ← top + 1
stack[top] ← data
end procedure
Implementation of this algorithm in C, is very easy. See the following code −
Example
void push(int data) {
if(!isFull()) {
top = top + 1;
stack[top] = data;
} else {
printf("Could not insert data, Stack is full.\n");
}
}
Pop Operation
Accessing the content while removing it from the stack, is known as a Pop Operation. In an array
implementation of pop() operation, the data element is not actually removed, instead top is
decremented to a lower position in the stack to point to the next value. But in linked-list
implementation, pop() actually removes data element and deallocates memory space.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 34
A Pop operation may involve the following steps −
Step 1 − Checks if the stack is empty.
Step 2 − If the stack is empty, produces an error and exit.
Step 3 − If the stack is not empty, accesses the data element at which top is pointing.
Step 4 − Decreases the value of top by 1.
Step 5 − Returns success.
Algorithm for Pop Operation
A simple algorithm for Pop operation can be derived as follows −
begin procedure pop: stack
if stack is empty
return null
endif
data ← stack[top]
top ← top - 1
return data
end procedure
Implementation of this algorithm in C, is as follows −
Example
int pop(int data) {
if(!isempty()) {
data = stack[top];
top = top - 1;
return data;
} else {
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 35
printf("Could not retrieve data, Stack is empty.\n");
}
}
7 ) What is a Binary Search Tree (BST) ? Make a BST for the following sequence of numbers
: 32, 68, 22, 95, 99, 26, 92, 84, 29, 36 Write Preorder, Inorder and Postorder Traversal
of this Tree.
Binary Search Tree | Set 1 (Search and Insertion)
The following is definition of Binary Search Tree(BST) according to Wikipedia
Binary Search Tree, is a node-based binary tree data structure which has the following properties:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than the node’s key.
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.
Searching a key
To search a given key in Bianry Search Tree, we first compare it with root, if the key is present at
root, we return root. If key is greater than root’s key, we recur for right subtree of root node.
Otherwise we recur for left subtree.
// C function to search a given key in a given BST
struct node* search(struct node* root, int key)
{
// Base Cases: root is null or key is present at root
if (root == NULL || root->key == key)
return root;
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 36
// Key is greater than root's key
if (root->key < key)
return search(root->right, key);
// Key is smaller than root's key
return search(root->left, key);
}
Time Complexity: The worst case time complexity of search and insert 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).
Some Interesting Facts:
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 37
Inorder traversal of BST always produces sorted output.
We can construct a BST with only Preorder or Postorder or Level Order traversal. Note that
we can always get inorder traversal by sorting the only given traversal.
Number of unique BSTs with n distinct keys is Catalan Number
b) Explain the AVL Tree and Complete Binary Tree.
Ans:- Refer previous year solved solution paper.
8) What is threaded binary tree ?
Ans:- Refer previous year solved solution paper.
9) Write an algorithm for following (Any One) :–
i) BFS
(ii) DFS
Also discuss suitable example of it.
Ans:- Refer previous year solved solution paper.
10. (a) Define and explain following terminology of a graph as a data structure with example
:––
(i) Path and cycle.
A graph is a pictorial representation of a set of objects where some pairs of objects are connected by
links. The interconnected objects are represented by points termed as vertices, and the links that
connect the vertices are called edges.
Formally, a graph is a pair of sets (V, E), where V is the set of vertices and E is the set of edges,
connecting the pairs of vertices. Take a look at the following graph −
In the above graph,
V = {a, b, c, d, e}
E = {ab, ac, bd, cd, de}
Graph Data Structure
Mathematical graphs can be represented in data structure. We can represent a graph using an array
of vertices and a two-dimensional array of edges. Before we proceed further, let's familiarize
ourselves with some important terms −
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 38
Vertex − Each node of the graph is represented as a vertex. In the following example, the
labeled circle represents vertices. Thus, A to G are vertices. We can represent them using an
array as shown in the following image. Here A can be identified by index 0. B can be
identified using index 1 and so on.
Edge − Edge represents a path between two vertices or a line between two vertices. In the
following example, the lines from A to B, B to C, and so on represents edges. We can use a
two-dimensional array to represent an array as shown in the following image. Here AB can
be represented as 1 at row 0, column 1, BC as 1 at row 1, column 2 and so on, keeping other
combinations as 0.
Adjacency − Two node or vertices are adjacent if they are connected to each other through
an edge. In the following example, B is adjacent to A, C is adjacent to B, and so on.
Path − Path represents a sequence of edges between the two vertices. In the following
example, ABCD represents a path from A to D.
Basic Operations
Following are basic primary operations of a Graph −
Add Vertex − Adds a vertex to the graph.
Add Edge − Adds an edge between the two vertices of the graph.
Display Vertex − Displays a vertex of the graph.
B) Shortest Path Problem
Shortest paths.
An edge-weighted digraph is a digraph where we associate weights or costs with each edge. A
shortest path from vertex s to vertex t is a directed path from s to t with the property that no other
such path has a lower weight.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 39
Properties.
We summarize several important properties and assumptions.
Paths are directed. A shortest path must respect the direction of its edges.
The weights are not necessarily distances. Geometric intuition can be helpful, but the edge
weights weights might represent time or cost.
Not all vertices need be reachable. If t is not reachable from s, there is no path at all, and
therefore there is no shortest path from s to t.
Negative weights introduce complications. For the moment, we assume that edge weights
are positive (or zero).
Shortest paths are normally simple. Our algorithms ignore zero-weight edges that form
cycles, so that the shortest paths they find have no cycles.
Shortest paths are not necessarily unique. There may be multiple paths of the lowest weight
from one vertex to another; we are content to find any one of them.
Parallel edges and self-loops may be present. In the text, we assume that parallel edges are
not present and use the notation v->w to refer to the edge from v to w, but our code handles
them without difficulty.
Edge-weighted digraph data type.
We represent the weighted edges using the following API:
The from() and to() methods are useful for accessing the edge's vertices. DirectedEdge.java
implements this API.
We represent edge-weighted digraphs using the following API:
EdgeWeightedDigraph.java implements the API using the adjacency-lists representation.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 40
Data structures for single-source shortest paths.
Given an edge-weighted digraph and a designated vertex s, a shortest-paths tree (SPT) is a
subgraph containing s and all the vertices reachable from s that forms a directed tree rooted at s
such that every tree path is a shortest path in the digraph.
We represent the shortest paths with two vertex-indexed arrays:
Edges on the shortest-paths tree: edgeTo[v] is the the last edge on a shortest path from s to
v.
Distance to the source: distTo[v] is the length of the shortest path from s to v.
B) i)Hamilton Path.
Ans:- Refer previous year solved solution paper.
ii)Spanning Tree.
A spanning tree is a subset of Graph G, which has all the vertices covered with minimum possible
number of edges. Hence, a spanning tree does not have cycles and it cannot be disconnected..
By this definition, we can draw a conclusion that every connected and undirected Graph G has at
least one spanning tree. A disconnected graph does not have any spanning tree, as it cannot be
spanned to all its vertices.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 41
We found three spanning trees off one complete graph. A complete undirected graph can have
maximum nn-2 number of spanning trees, where n is the number of nodes. In the above addressed
example, 33−2 = 3 spanning trees are possible.
General Properties of Spanning Tree
We now understand that one graph can have more than one spanning tree. Following are a few
properties of the spanning tree connected to graph G −
A connected graph G can have more than one spanning tree.
All possible spanning trees of graph G, have the same number of edges and vertices.
The spanning tree does not have any cycle (loops).
Removing one edge from the spanning tree will make the graph disconnected, i.e. the
spanning tree is minimally connected.
Adding one edge to the spanning tree will create a circuit or loop, i.e. the spanning tree is
maximally acyclic.
Mathematical Properties of Spanning Tree
Spanning tree has n-1 edges, where n is the number of nodes (vertices).
From a complete graph, by removing maximum e - n + 1 edges, we can construct a
spanning tree.
A complete graph can have maximum nn-2 number of spanning trees.
Thus, we can conclude that spanning trees are a subset of connected Graph G and disconnected
graphs do not have spanning tree.
Application of Spanning Tree
Spanning tree is basically used to find a minimum path to connect all nodes in a graph. Common
application of spanning trees are −
Civil Network Planning
Computer Network Routing Protocol
Cluster Analysis
Let us understand this through a small example. Consider, city network as a huge graph and now
plans to deploy telephone lines in such a way that in minimum lines we can connect to all city
nodes. This is where the spanning tree comes into picture.
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 42
Minimum Spanning Tree (MST)
In a weighted graph, a minimum spanning tree is a spanning tree that has minimum weight than all
other spanning trees of the same graph. In real-world situations, this weight can be measured as
distance, congestion, traffic load or any arbitrary value denoted to the edges.
Minimum Spanning-Tree Algorithm
We shall learn about two most important spanning tree algorithms here −
Kruskal's Algorithm
Prim's Algorithm
Both are greedy algorithms.
11A)What is collision in hashing ? How can it be avoided ? What are the different collision
handling mechanisms ? Explain each with suitable example
Ans:- Refer previous year solved solution paper.
12) What is symbol table ? What are different data structures used for symbol table ? Discuss.
In computer science, a symbol table is a data structure used by a language translator such as a
compiler or interpreter, where each identifier in a program's source code is associated with
information relating to its declaration or appearance in the source.
Implementation
A common implementation technique is to use a hash table. A compiler may use one large symbol
table for all symbols or use separated, hierarchical symbol tables for different scopes. There are also
trees, linear lists and self-organizing lists which can be used to implement a symbol table. It also
simplifies the classification of literals in tabular format. The symbol table is accessed by most
phases of a compiler, beginning with the lexical analysis to optimization.
Uses
An object file will contain a symbol table of the identifiers it contains that are externally visible.
During the linking of different object files, a linker will use these symbol tables to resolve any
unresolved references.
A symbol table may only exist during the translation process, or it may be embedded in the output
of that process for later exploitation, for example, during an interactive debugging session, or as a
resource for formatting a diagnostic report during or after execution of a program.
While reverse engineering an executable, many tools refer to the symbol table to check what
addresses have been assigned to global variables and known functions. If the symbol table has been
stripped or cleaned out before being converted into an executable, tools will find it harder to
determine addresses or understand anything about the program.
At that time of accessing variables and allocating memory dynamically, a compiler should perform
many works and as such the extended stack model requires the symbol table.
Example
TGPCET/CSE/ Solution Set-S 17
DSPD Ms. Neha V. Mogre Page 43
Consider the following program written in C:
// Declare an external function
extern double bar(double x);
// Define a public function
double foo(int count)
{
double sum = 0.0;
// Sum all the values bar(1) to bar(count)
for (int i = 1; i <= count; i++)
sum += bar((double) i);
return sum;
}
A C compiler that parses this code will contain at least the following symbol table entries:
Symbol name Type Scope
bar function, double extern
x double function parameter
foo function, double global
count int function parameter
sum double block local
i int for-loop statement
In addition, the symbol table will also contain entries generated by the compiler for intermediate
expression values (e.g., the expression that casts the i loop variable into a double, and the return
value of the call to function bar()), statement labels, and so forth.
As another example, the symbol table of a small program is listed below. The table itself was
generated using the GNU binutils' nm utility. There is one data symbol, (noted by the "D" type),
and many functions (self defined as well as from the standard library). The first column is where the
symbol is located in the memory, the second is "The symbol type" and the third is the name of the
symbol. By passing suitable parameters, the symbol table was made to sort on basis of address.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 1
Tulsiramji Gaikwad-Patil College of Engineering and Technology
Department of Computer Science and Engineering
Semester : B.E. Fourth Semester
Subject : DSPD
Solution Set: Winter – 2017
1a) Explain the various sorting techniques. Give its time complexities.
Bubble Sort [Best: O(n), Worst:O(N^2)]
Starting on the left, compare adjacent items and keep “bubbling” the larger one to the right (it’s in
its final place). Bubble sort the remaining N -1 items.
Though “simple” I found bubble sort nontrivial. In general, sorts where you iterate
backwards (decreasing some index) were counter-intuitive for me. With bubble-sort, either
you bubble items “forward” (left-to-right) and move the endpoint backwards (decreasing),
or bubble items “backward” (right-to-left) and increase the left endpoint. Either way, some
index is decreasing.
You also need to keep track of the next-to-last endpoint, so you don’t swap with a non-
existent item.
Selection Sort [Best/Worst: O(N^2)]
Scan all items and find the smallest. Swap it into position as the first item. Repeat the selection sort
on the remaining N-1 items.
I found this the most intuitive and easiest to implement — you always iterate forward (i
from 0 to N-1), and swap with the smallest element (always i).
Insertion Sort [Best: O(N), Worst:O(N^2)]
Start with a sorted list of 1 element on the left, and N-1 unsorted items on the right. Take the first
unsorted item (element #2) and insert it into the sorted list, moving elements as necessary. We now
have a sorted list of size 2, and N -2 unsorted elements. Repeat for all elements.
Like bubble sort, I found this counter-intuitive because you step “backwards”
This is a little like bubble sort for moving items, except when you encounter an item smaller
than you, you stop. If the data is reverse-sorted, each item must travel to the head of the list,
and this becomes bubble-sort.
There are various ways to move the item leftwards — you can do a swap on each iteration,
or copy each item over its neighbor
Radix sort [Best/Avg/Worst: O(N)]
Get a series of numbers, and sort them one digit at a time (moving all the 1000’s ahead of the
2000’s, etc.). Repeat the sorting on each set of digits.
Radix sort uses counting sort for efficient O(N) sorting of the digits (k = 0…9)
Actually, radix sort goes from least significant digit (1’s digit) to most significant, for
reasons I’ll explain later (see CLRS book)
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 2
Radix & counting sort are fast, but require structured data, external memory and do not have
the caching benefits of quicksort.
1 b) Write an algorithm of Bubble sort.
Bubble Sort
The algorithm works by comparing each item in the list with the item next to it, and swapping them
if required. In other words, the largest element has bubbled to the top of the array. The algorithm
repeats this process until it makes a pass all the way through the list without swapping any items.
void bubbleSort(int ar[])
{
for (int i = (ar.length - 1); i >= 0; i--)
{
for (int j = 1; j ≤ i; j++)
{
if (ar[j-1] > ar[j])
{
int temp = ar[j-1];
ar[j-1] = ar[j];
ar[j] = temp;
} } } }
Example. Here is one step of the algorithm. The largest element - 7 - is bubbled to the top:
7, 5, 2, 4, 3, 9
5, 7, 2, 4, 3, 9
5, 2, 7, 4, 3, 9
5, 2, 4, 7, 3, 9
5, 2, 4, 3, 7, 9
5, 2, 4, 3, 7, 9
The worst-case runtime complexity is O(n2). See explanation below
2 a) Write a program to implement Binary Search
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 3
#include <stdio.h>
int main()
{
int c, first, last, middle, n, search, array[100];
printf("Enter number of elements\n");
scanf("%d",&n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d",&array[c]);
printf("Enter value to find\n");
scanf("%d", &search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while (first <= last) {
if (array[middle] < search)
first = middle + 1;
else if (array[middle] == search) {
printf("%d found at location %d.\n", search, middle+1);
break;
}
else
last = middle - 1;
middle = (first + last)/2;
}
if (first > last)
printf("Not found! %d is not present in the list.\n", search);
return 0;
}
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 4
2b) Explain the following terms :––
i)Sparse Matrix.
What is Sparse Matrix?
In computer programming, a matrix can be defined with a 2-dimensional array. Any array with 'm'
columns and 'n' rows represents a mXn matrix. There may be a situation in which a matrix contains
more number of ZERO values than NON-ZERO values. Such matrix is known as sparse matrix.
Sparse matrix is a matrix which contains very few non-zero elements.
When a sparse matrix is represented with 2-dimensional array, we waste lot of space to represent
that matrix. For example, consider a matrix of size 100 X 100 containing only 10 non-zero
elements. In this matrix, only 10 spaces are filled with non-zero values and remaining spaces of
matrix are filled with zero. That means, totally we allocate 100 X 100 X 2 = 20000 bytes of space to
store this integer matrix. And to access these 10 non-zero elements we have to make scanning for
10000 times.
Sparse Matrix Representations
A sparse matrix can be represented by using TWO representations, those are as follows...
1. Triplet Representation
2. Linked Representation
Triplet Representation
In this representation, we consider only non-zero values along with their row and column index
values. In this representation, the 0th row stores total rows, total columns and total non-zero values
in the matrix.
For example, consider a matrix of size 5 X 6 containing 6 number of non-zero values. This matrix
can be represented as shown in the image...
In above example matrix, there are only 6 non-zero elements ( those are 9, 8, 4, 2, 5 & 2) and
matrix size is 5 X 6. We represent this matrix as shown in the above image. Here the first row in the
right side table is filled with values 5, 6 & 6 which indicates that it is a sparse matrix with 5 rows, 6
columns & 6 non-zero values. Second row is filled with 0, 4, & 9 which indicates the value in the
matrix at 0th row, 4th column is 9. In the same way the remaining non-zero values also follows the
similar pattern.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 5
Linked Representation
In linked representation, we use linked list data structure to represent a sparse matrix. In this linked
list, we use two different nodes namely header node and element node. Header node consists of
three fields and element node consists of five fields as shown in the image...
Consider the above same sparse matrix used in the Triplet representation. This sparse matrix can be
represented using linked representation as shown in the below image...
In above representation, H0, H1,...,H5 indicates the header nodes which are used to represent
indexes. Remaining nodes are used to represent non-zero elements in the matrix, except the very
first node which is used to represent abstract information of the sparse matrix (i.e., It is a matrix of
5 X 6 with 6 non-zero elements).
In this representation, in each row and column, the last node right field points to it's respective
header node.
2) What is Time complexity?
Every algorithm requires some amount of computer time to execute its instruction to perform the
task. This computer time required is called time complexity.
Time complexity of an algorithm can be defined as follows...
The time complexity of an algorithm is the total amount of time required by an algorithm to
complete its execution.
Generally, running time of an algorithm depends upon the following...
1. Whether it is running on Single processor machine or Multi processor machine.
2. Whether it is a 32 bit machine or 64 bit machine
3. Read and Write speed of the machine.
4. The time it takes to perform Arithmetic operations, logical operations, return value and
assignment operations etc.,
5. Input data
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 6
NOTE
☀ When we calculate time complexity of an algorithm, we consider only input data and ignore the
remaining things, as they are machine dependent. We check only, how our program is behaving for
the different input values to perform all the operations like Arithmetic, Logical, Return value and
Assignment etc.,
Calculating Time Complexity of an algorithm based on the system configuration is a very difficult
task because, the configuration changes from one system to another system. To solve this problem,
we must assume a model machine with specific configuration. So that, we can able to calculate
generalized time complexity according to that model machine.
To calculate time complexity of an algorithm, we need to define a model machine. Let us assume a
machine with following configuration...
1. Single processor machine
2. 32 bit Operating System machine
3. It performs sequential execution
4. It requires 1 unit of time for Arithmetic and Logical operations
5. It requires 1 unit of time for Assignment and Return value
6. It requires 1 unit of time for Read and Write operations
Now, we calculate the time complexity of following example code by using the above defined
model machine...
Example 1
Consider the following piece of code...
int sum(int a, int b)
{
return a+b;
}
In above sample code, it requires 1 unit of time to calculate a+b and 1 unit of time to return the
value. That means, totally it takes 2 units of time to complete its execution. And it does not change
based on the input values of a and b. That means for all input values, it requires same amount of
time i.e. 2 units.
If any program requires fixed amount of time for all input values then its time complexity is said to
be Constant Time Complexity.
For the above code, time complexity can be calculated as follows...
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 7
In above calculation
Cost is the amount of computer time required for a single operation in each line.
Repeatation is the amount of computer time required by each operation for all its repeatations.
Total is the amount of computer time required by each operation to execute.
So above code requires '4n+4' Units of computer time to complete the task. Here the exact time is
not fixed. And it changes based on the n value. If we increase the n value then the time required
also increases linearly.
Totally it takes '4n+4' units of time to complete its execution and it is Linear Time Complexity.
If the amount of time required by an algorithm is increased with the increase of input value then
that time complexity is said to be Linear Time Complexity
3) What is Space complexity?
When we design an algorithm to solve a problem, it needs some computer memory to complete its
execution. For any algorithm, memory is required for the following purposes...
1. Memory required to store program instructions
2. Memory required to store constant values
3. Memory required to store variable values
4. And for few other things
Space complexity of an algorithm can be defined as follows...
Total amount of computer memory required by an algorithm to complete its execution is called as
space complexity of that algorithm
Generally, when a program is under execution it uses the computer memory for THREE reasons.
They are as follows...
1. Instruction Space: It is the amount of memory used to store compiled version of
instructions.
2. Environmental Stack: It is the amount of memory used to store information of partially
executed functions at the time of function call.
3. Data Space: It is the amount of memory used to store all the variables and constants.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 8
NOTE
☀ When we want to perform analysis of an algorithm based on its Space complexity, we consider
only Data Space and ignore Instruction Space as well as Environmental Stack.
That means we calculate only the memory required to store Variables, Constants, Structures, etc.,
To calculate the space complexity, we must know the memory required to store different datatype
values (according to the compiler). For example, the C Programming Language compiler requires
the following...
1. 2 bytes to store Integer value,
2. 4 bytes to store Floating Point value,
3. 1 byte to store Character value,
4. 6 (OR) 8 bytes to store double value
Example 1
Consider the following piece of code...
int square(int a)
{
return a*a;
}
In above piece of code, it requires 2 bytes of memory to store variable 'a' and another 2 bytes of
memory is used for return value.
That means, totally it requires 4 bytes of memory to complete its execution. And this 4 bytes
of memory is fixed for any input value of 'a'. This space complexity is said to be Constant
Space Complexity.
If any algorithm requires a fixed amount of space for all input values then that space complexity is
said to be Constant Space Complexity
Example 2
Consider the following piece of code...
int sum(int A[], int n)
{
int sum = 0, i;
for(i = 0; i < n; i++)
sum = sum + A[i];
return sum;
}
In above piece of code it requires
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 9
'n*2' bytes of memory to store array variable 'a[]'
2 bytes of memory for integer parameter 'n'
4 bytes of memory for local integer variables 'sum' and 'i' (2 bytes each)
2 bytes of memory for return value.
That means, totally it requires '2n+8' bytes of memory to complete its execution. Here, the
amount of memory depends on the input value of 'n'. This space complexity is said to be
Linear Space Complexity.
If the amount of space required by an algorithm is increased with the increase of input value, then
that space complexity is said to be Linear Space Complexity
3a) Write a Menu Driven Program for various operations of singly linked list.
#include<stdio.h>
#include<conio.h>
#include<process.h>
struct node
{
int data;
struct node *next;
}*start=NULL,*q,*t;
int main()
{
int ch;
void insert_beg();
void insert_end();
int insert_pos();
void display();
void delete_beg();
void delete_end();
int delete_pos();
while(1)
{
printf("\n\n---- Singly Linked List(SLL) Menu ----");
printf("\n1.Insert\n2.Display\n3.Delete\n4.Exit\n\n");
printf("Enter your choice(1-4):");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("\n---- Insert Menu ----");
printf("\n1.Insert at beginning\n2.Insert at end\n3.Insert at specified position\n4.Exit");
printf("\n\nEnter your choice(1-4):");
scanf("%d",&ch);
switch(ch)
{
case 1: insert_beg();
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 10
break;
case 2: insert_end();
break;
case 3: insert_pos();
break;
case 4: exit(0);
default: printf("Wrong Choice!!");
}
break;
case 2: display();
break;
case 3: printf("\n---- Delete Menu ----");
printf("\n1.Delete from beginning\n2.Delete from end\n3.Delete from specified
position\n4.Exit");
printf("\n\nEnter your choice(1-4):");
scanf("%d",&ch);
switch(ch)
{
case 1: delete_beg();
break;
case 2: delete_end();
break;
case 3: delete_pos();
break;
case 4: exit(0);
default: printf("Wrong Choice!!");
}
break;
case 4: exit(0);
default: printf("Wrong Choice!!");
}
}
return 0;
}
void insert_beg()
{
int num;
t=(struct node*)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&num);
t->data=num;
if(start==NULL) //If list is empty
{
t->next=NULL;
start=t;
}
else
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 11
{
t->next=start;
start=t;
}
}
void insert_end()
{
int num;
t=(struct node*)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&num);
t->data=num;
t->next=NULL;
if(start==NULL) //If list is empty
{
start=t;
}
else
{
q=start;
while(q->next!=NULL)
q=q->next;
q->next=t;
}
}
int insert_pos()
{
int pos,i,num;
if(start==NULL)
{
printf("List is empty!!");
return 0;
}
t=(struct node*)malloc(sizeof(struct node));
printf("Enter data:");
scanf("%d",&num);
printf("Enter position to insert:");
scanf("%d",&pos);
t->data=num;
q=start;
for(i=1;i<pos-1;pos++)
{
if(q->next==NULL)
{
printf("There are less elements!!");
return 0;
}
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 12
q=q->next;
}
t->next=q->next;
q->next=t;
return 0;
}
void display()
{
if(start==NULL)
{
printf("List is empty!!");
}
else
{
q=start;
printf("The linked list is:\n");
while(q!=NULL)
{
printf("%d->",q->data);
q=q->next;
}
}
}
void delete_beg()
{
if(start==NULL)
{
printf("The list is empty!!");
}
else
{
q=start;
start=start->next;
printf("Deleted element is %d",q->data);
free(q);
}
}
void delete_end()
{
if(start==NULL)
{
printf("The list is empty!!");
}
else
{
q=start;
while(q->next->next!=NULL)
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 13
q=q->next;
t=q->next;
q->next=NULL;
printf("Deleted element is %d",t->data);
free(t);
}
}
int delete_pos()
{
int pos,i;
if(start==NULL)
{
printf("List is empty!!");
return 0;
}
printf("Enter position to delete:");
scanf("%d",&pos);
for(i=1;i<pos-1;pos++)
{
if(q->next==NULL)
{
printf("There are less elements!!");
return 0;
}
q=q->next;
}
t=q->next;
q->next=t->next;
printf("Deleted element is %d",t->data);
free(t);
return 0;
}
Output —- Singly Linked List(SLL) Menu —-
1.Insert
2.Display
3.Delete
4.ExitEnter your choice(1-4):1—- Insert Menu —-
1.Insert at beginning
2.Insert at end
3.Insert at specified position
4.Exit
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 14
Enter your choice(1-4):1
Enter data:4
—- Singly Linked List(SLL) Menu —-
1.Insert
2.Display
3.Delete
4.Exit
Enter your choice(1-4):2
The linked list is:
4->
—- Singly Linked List(SLL) Menu —-
1.Insert
2.Display
3.Delete
4.Exit
Enter your choice(1-4):4
3 b) Give suitable representation for polynomials and write an algorithm to add two
polynomials.
Program to add two polynomials
Given two polynomials represented by two arrays, write a function that adds given two
polynomials.
Example:
Input: A[] = {5, 0, 10, 6}
B[] = {1, 2, 4}
Output: sum[] = {5, 10, 30, 26, 52, 24}
The first input array represents "5 + 0x^1 + 10x^2 + 6x^3"
The second array represents "1 + 2x^1 + 4x^2"
And Output is "6 + 2x^1 + 14x^2 + 6x^3"
Addition is simpler than multiplication of polynomials. We initialize result as one of the two
polynomials, then we traverse the other polynomial and add all terms to the result.
add(A[0..m-1], B[0..n01])
1) Create a sum array sum[] of size equal to maximum of 'm' and 'n'
2) Copy A[] to sum[].
3) Travers array B[] and do following for every element B[i]
sum[i] = sum[i] + B[i]
4) Return sum[].
The following is C++ implementation of above algorithm.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 15
// Simple C++ program to add two polynomials
#include <iostream>
using namespace std;
// A utility function to return maximum of two integers
int max(int m, int n) { return (m > n)? m: n; }
// A[] represents coefficients of first polynomial
// B[] represents coefficients of second polynomial
// m and n are sizes of A[] and B[] respectively
int *add(int A[], int B[], int m, int n)
{
int size = max(m, n);
int *sum = new int[size];
// Initialize the porduct polynomial
for (int i = 0; i<m; i++)
sum[i] = A[i];
// Take ever term of first polynomial
for (int i=0; i<n; i++)
sum[i] += B[i];
return sum;
}
// A utility function to print a polynomial
void printPoly(int poly[], int n)
{
for (int i=0; i<n; i++)
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 16
{
cout << poly[i];
if (i != 0)
cout << "x^" << i ;
if (i != n-1)
cout << " + ";
}
}
// Driver program to test above functions
int main()
{
// The following array represents polynomial 5 + 10x^2 + 6x^3
int A[] = {5, 0, 10, 6};
// The following array represents polynomial 1 + 2x + 4x^2
int B[] = {1, 2, 4};
int m = sizeof(A)/sizeof(A[0]);
int n = sizeof(B)/sizeof(B[0]);
cout << "First polynomial is \n";
printPoly(A, m);
cout << "\nSecond polynomial is \n";
printPoly(B, n);
int *sum = add(A, B, m, n);
int size = max(m, n);
cout << "\nsumuct polynomial is \n";
printPoly(sum, size);
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 17
return 0;
}
Output:
First polynomial is
5 + 0x^1 + 10x^2 + 6x^3
Second polynomial is
1 + 2x^1 + 4x^2
Sum polynomial is
6 + 2x^1 + 14x^2 + 6x^3
Time complexity of the above algorithm and program is O(m+n) where m and n are orders of two
given polynomials.
4) Write a function to :––
(i) Insert a node at end in doubly linked list
Insertion At Last in doubly linked list
Algorithm
1. InsertAtEndDll(info,prev,next,start,end)
2. 1.create a new node and address in assigned to ptr.
3. 2.check[overflow] if(ptr=NULL)
4. write:overflow and exit
5. 3.set Info[ptr]=item;
6. 4.if(start=NULL)
7. set prev[ptr] = next[ptr] = NULL
8. set start = end = ptr
9. else
10. set prev[ptr] = end
11. next[end] = ptr
12. set ptr[next] = NULL
13. set end = ptr
14. [end if]
15. 5.Exit.
b)Delete a node from a specific position from doubly linked list.
Algorithm to delete node from any position of a doubly linked list
Algorithm to delete node from any position
%% Input : head {Pointer to the first node of the list}
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 18
last {Pointer to the last node of the list}
N {Position to be deleted from list}
Begin:
current ← head;
For i ← 1 to N and current != NULL do
current ← current.next;
End for
If (N == 1) then
deleteFromBeginning()
End if Else if (current == last) then
deleteFromEnd()
End if
Else if (current != NULL) then
current.prev.next ← current.next
If (current.next != NULL) then
current.next.prev ← current.prev;
End if unalloc (current)
write ('Node deleted successfully from ', N, ' position')
End if
Else then
write ('Invalid position')
End if
End
4b) What is static memory allocation and dynamic memory allocation ? What are the
functions used for dynamic memory allocation in ''C'' ? Give examples.
static memory allocation and dynamic memory allocation:-
Static Memory Allocation: Memory is allocated for the declared variable by the compiler. The
address can be obtained by using ‘address of’ operator and can be assigned to a pointer. The
memory is allocated during compile time. Since most of the declared variables have static memory,
this kind of assigning the address of a variable to a pointer is known as static memory allocation.
Dynamic Memory Allocation: Allocation of memory at the time of execution (run time) is known
as dynamic memory allocation. The functions calloc() and malloc() support allocating of dynamic
memory. Dynamic allocation of memory space is done by using these functions when value is
returned by functions and assigned to pointer variables.
In C, the exact size of array is unknown until compile time, i.e., the time when a compiler compiles
your code into a computer understandable language. So, sometimes the size of the array can be
insufficient or more than required.
Dynamic memory allocation allows your program to obtain more memory space while running, or
to release it if it's not required.
In simple terms, Dynamic memory allocation allows you to manually handle memory space for
your program.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 19
Although, C language inherently does not have any technique to allocate memory dynamically,
there are 4 library functions under "stdlib.h" for dynamic memory allocation.
Function Use of Function
malloc() Allocates requested size of bytes and returns a pointer first byte of allocated space
calloc()
Allocates space for an array elements, initializes to zero and then returns a pointer to
memory
free() deallocate the previously allocated space
realloc() Change the size of previously allocated space
C malloc()
The name malloc stands for "memory allocation".
The function malloc() reserves a block of memory of specified size and return a pointer of type void
which can be casted into pointer of any form.
Syntax of malloc()
ptr = (cast-type*) malloc(byte-size)
Here, ptr is pointer of cast-type. The malloc() function returns a pointer to an area of memory with
size of byte size. If the space is insufficient, allocation fails and returns NULL pointer.
ptr = (int*) malloc(100 * sizeof(int));
This statement will allocate either 200 or 400 according to size of int 2 or 4 bytes respectively and
the pointer points to the address of first byte of memory.
C calloc()
The name calloc stands for "contiguous allocation".
The only difference between malloc() and calloc() is that, malloc() allocates single block of
memory whereas calloc() allocates multiple blocks of memory each of same size and sets all bytes
to zero.
Syntax of calloc()
ptr = (cast-type*)calloc(n, element-size);
This statement will allocate contiguous space in memory for an array of n elements. For example:
ptr = (float*) calloc(25, sizeof(float));
This statement allocates contiguous space in memory for an array of 25 elements each of size of
float, i.e, 4 bytes.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 20
C free()
Dynamically allocated memory created with either calloc() or malloc() doesn't get freed on its own.
You must explicitly use free() to release the space.
syntax of free()
free(ptr);
This statement frees the space allocated in the memory pointed by ptr.
5a) Write an algorithm which convert infix expression into postfix from using stack and give
steps of each.
nfix to Postfix Conversion
Procedure for Postfix Conversion
1. Scan the Infix string from left to right.
2. Initialize an empty stack.
3. If the scanned character is an operand, add it to the Postfix string.
4. If the scanned character is an operator and if the stack is empty push the character to stack.
5. If the scanned character is an Operator and the stack is not empty, compare the precedence of
the character with the element on top of the stack.
6.
If top Stack has higher precedence over the scanned character pop the stack else push the
scanned character to stack. Repeat this step until the stack is not empty and top Stack has
precedence over the character.
7. Repeat 4 and 5 steps till all the characters are scanned.
8. After all characters are scanned, we have to add any character that the stack may have to the
Postfix string.
9. If stack is not empty add top Stack to Postfix string and Pop the stack.
10. Repeat this step as long as stack is not empty.
Algorithm for Postfix Conversion
1. S:stack
2. while(more tokens)
3. x<=next token
4. if(x == operand)
5. print x
6. else
7. while(precedence(x)<=precedence(top(s)))
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 21
8. print(pop(s))
9. push(s,x)
10. while(! empty (s))
11. print(pop(s))
Conversion To Postfix
EXAMPLE:
A+(B*C-(D/E-F)*G)*H
Stack Input Output
Empty A+(B*C-(D/E-F)*G)*H -
Empty +(B*C-(D/E-F)*G)*H A
+ (B*C-(D/E-F)*G)*H A
+( B*C-(D/E-F)*G)*H A
+( *C-(D/E-F)*G)*H AB
+(* C-(D/E-F)*G)*H AB
+(* -(D/E-F)*G)*H ABC
+(- (D/E-F)*G)*H ABC*
+(-( D/E-F)*G)*H ABC*
+(-( /E-F)*G)*H ABC*D
+(-(/ E-F)*G)*H ABC*D
+(-(/ -F)*G)*H ABC*DE
+(-(- F)*G)*H ABC*DE/
+(-(- F)*G)*H ABC*DE/
+(-(- )*G)*H ABC*DE/F
+(- *G)*H ABC*DE/F-
+(-* G)*H ABC*DE/F-
+(-* )*H ABC*DE/F-G
+ *H ABC*DE/F-G*-
+* H ABC*DE/F-G*-
+* End ABC*DE/F-G*-H
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 22
Empty End ABC*DE/F-G*-H*+
Infix to postfix implementation in c
1. #include <stdio.h>
2. #include <conio.h>
3. #include <ctype.h>
4. #define SIZE 50
5. char s[SIZE];
6. int top=-1;
7. push(char elem)
8. {
9. s[++top]=elem;
10. }
11.
12. char pop()
13. {
14. return(s[top--]);
15. }
16.
17. int pr(char elem)
18. {
19. switch(elem)
20. {
21. case '#': return 0;
22. case '(': return 1;
23. case '+':
24. case '-': return 2;
25. case '*':
26. case '/': return 3;
27. }
28. }
29.
30. void main()
31. {
32. char infx[50],pofx[50],ch,elem;
33. int i=0,k=0;
34. clrscr();
35. printf("\n\nRead the Infix Expression ? ");
36. scanf("%s",infx);
37. push('#');
38. while( (ch=infx[i++]) != '\0')
39. {
40. if( ch == '(') push(ch);
41. else
42. if(isalnum(ch)) pofx[k++]=ch;
43. else
44. if( ch == ')')
45. {
46. while( s[top] != '(')
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 23
47. pofx[k++]=pop();
48. elem=pop();
49. }
50. else
51. {
52. while( pr(s[top]) >= pr(ch) )
53. pofx[k++]=pop();
54. push(ch);
55. }
56. }
57. while( s[top] != '#')
58. pofx[k++]=pop();
59. pofx[k]='\0';
60. printf("\n\nGiven Infix Expn: %s Postfix Expn: %s\n",infx,pofx);
61. getch();
62. }
Output
5 a)Briefly explain :––
i) Deque.(Refer 2016 paper)
ii) Priority Queues.
Priority Queue is more specialized data structure than Queue. Like ordinary queue, priority
queue has same method but with a major difference. In Priority queue items are ordered by key
value so that item with the lowest value of key is at front and item with the highest value of key is
at rear or vice versa. So we're assigned priority to item based on its key value. Lower the value,
higher the priority. Following are the principal methods of a Priority Queue.
Basic Operations
insert / enqueue − add an item to the rear of the queue.
remove / dequeue − remove an item from the front of the queue.
Priority Queue Representation
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 24
We're going to implement Queue using array in this article. There is few more operations supported
by queue which are following.
Peek − get the element at front of the queue.
isFull − check if queue is full.
isEmpty − check if queue is empty.
Insert / Enqueue Operation
Whenever an element is inserted into queue, priority queue inserts the item according to its order.
Here we're assuming that data with high value has low priority.
6a) What do you mean by circular queues ? Give the array implementation of it and write an
algorithm for insertion and deletion of elements from circular queues.
Circular Queue
In a normal Queue Data Structure, we can insert elements until queue becomes full. But once if
queue becomes full, we can not insert the next element until all the elements are deleted from the
queue. For example consider the queue below...
After inserting all the elements into the queue.
Now consider the following situation after deleting three elements from the queue...
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 25
This situation also says that Queue is Full and we can not insert the new element because, 'rear' is
still at last position. In above situation, even though we have empty positions in the queue we can
not make use of them to insert new element. This is the major problem in normal queue data
structure. To overcome this problem we use circular queue data structure.
Implementation of Circular Queue
To implement a circular queue data structure using array, we first perform the following steps
before we implement actual operations.
Step 1: Include all the header files which are used in the program and define a constant
'SIZE' with specific value.
Step 2: Declare all user defined functions used in circular queue implementation.
Step 3: Create a one dimensional array with above defined SIZE (int cQueue[SIZE])
Step 4: Define two integer variables 'front' and 'rear' and initialize both with '-1'. (int
front = -1, rear = -1)
Step 5: Implement main method by displaying menu of operations list and make suitable
function calls to perform operation selected by the user on circular queue.
enQueue(value) - Inserting value into the Circular Queue
In a circular queue, enQueue() is a function which is used to insert an element into the circular
queue. In a circular queue, the new element is always inserted at rear position. The enQueue()
function takes one integer value as parameter and inserts that value into the circular queue. We can
use the following steps to insert an element into the circular queue...
Step 1: Check whether queue is FULL. ((rear == SIZE-1 && front == 0) || (front ==
rear+1))
Step 2: If it is FULL, then display "Queue is FULL!!! Insertion is not possible!!!" and
terminate the function.
Step 3: If it is NOT FULL, then check rear == SIZE - 1 && front != 0 if it is TRUE,
then set rear = -1.
Step 4: Increment rear value by one (rear++), set queue[rear] = value and check 'front ==
-1' if it is TRUE, then set front = 0.
deQueue() - Deleting a value from the Circular Queue
In a circular queue, deQueue() is a function used to delete an element from the circular queue. In a
circular queue, the element is always deleted from front position. The deQueue() function doesn't
take any value as parameter. We can use the following steps to delete an element from the circular
queue...
Step 1: Check whether queue is EMPTY. (front == -1 && rear == -1)
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 26
Step 2: If it is EMPTY, then display "Queue is EMPTY!!! Deletion is not possible!!!"
and terminate the function.
Step 3: If it is NOT EMPTY, then display queue[front] as deleted element and increment
the front value by one (front ++). Then check whether front == SIZE, if it is TRUE, then
set front = 0. Then check whether both front - 1 and rear are equal (front -1 == rear), if it
TRUE, then set both front and rear to '-1' (front = rear = -1).
display() - Displays the elements of a Circular Queue
We can use the following steps to display the elements of a circular queue...
Step 1: Check whether queue is EMPTY. (front == -1)
Step 2: If it is EMPTY, then display "Queue is EMPTY!!!" and terminate the function.
Step 3: If it is NOT EMPTY, then define an integer variable 'i' and set 'i = front'.
Step 4: Check whether 'front <= rear', if it is TRUE, then display 'queue[i]' value and
increment 'i' value by one (i++). Repeat the same until 'i <= rear' becomes FALSE.
Step 5: If 'front <= rear' is FALSE, then display 'queue[i]' value and increment 'i' value by
one (i++). Repeat the same until'i <= SIZE - 1' becomes FALSE.
Step 6: Set i to 0.
Step 7: Again display 'cQueue[i]' value and increment i value by one (i++). Repeat the
same until 'i <= rear' becomes FALSE.
Program to implement Queue using Array
#include<stdio.h>
#include<conio.h>
#define SIZE 5
void enQueue(int);
void deQueue();
void display();
int cQueue[SIZE], front = -1, rear = -1;
void main()
{
int choice, value;
clrscr();
while(1){
printf("\n****** MENU ******\n");
printf("1. Insert\n2. Delete\n3. Display\n4. Exit\n");
printf("Enter your choice: ");
scanf("%d",&choice);
switch(choice){
case 1: printf("\nEnter the value to be insert: ");
scanf("%d",&value);
enQueue(value);
break;
case 2: deQueue();
break;
case 3: display();
break;
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 27
case 4: exit(0);
default: printf("\nPlease select the correct choice!!!\n");
}
}
}
void enQueue(int value)
{
if((front == 0 && rear == SIZE - 1) || (front == rear+1))
printf("\nCircular Queue is Full! Insertion not possible!!!\n");
else{
if(rear == SIZE-1 && front != 0)
rear = -1;
cQueue[++rear] = value;
printf("\nInsertion Success!!!\n");
if(front == -1)
front = 0;
}
}
void deQueue()
{
if(front == -1 && rear == -1)
printf("\nCircular Queue is Empty! Deletion is not possible!!!\n");
else{
printf("\nDeleted element : %d\n",cQueue[front++]);
if(front == SIZE)
front = 0;
if(front-1 == rear)
front = rear = -1;
}
}
void display()
{
if(front == -1)
printf("\nCircular Queue is Empty!!!\n");
else{
int i = front;
printf("\nCircular Queue Elements are : \n");
if(front <= rear){
while(i <= rear)
printf("%d\t",cQueue[i++]);
}
else{
while(i <= SIZE - 1)
printf("%d\t", cQueue[i++]);
i = 0;
while(i <= rear)
printf("%d\t",cQueue[i++]);
}
}
}
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 28
Output
7) Explain the terms :––
i) Polish Notations
The name comes from the Polish mathematician/logician Lukasiewicz, who introduced it. Three
types:
Infix form
Prefix form
Postfix form
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 29
Infix form
Is exactly the fully parenthesized notation we have just introduced. Let me remind you once again
the Recursive definition
infix-expression := (infix-expression operand infix-expression)
infix-expression := atom
Examples
(3 * 7)
((1 + 3) * 2)
((1 + 3) * ( 2 - 3))
Main Feature: the binary operator is between the two operands.
Question: what if we do not put all the parentheses? Then there are ambiguities on how to interpret
an expression: is 1+2*3 the same as (1+2)*3 or the same as 1+(2*3)? The precedence of operators
solves this problem.
Prefix form
Main Feature: the operator preceeds the two operands.
Recursive definition of fully parenthesized version:
prefix-expression := (operand prefix-expression prefix-expression)
prefix-expression := atom
Recursive definition of classic version, without parentheses (we do not need them, because there is
no longer any ambiguity on how to match the operands to the operators):
prefix-expression := operand prefix-expression prefix-expression
prefix-expression := atom
Examples
(* 3 7) or simply * 3 7
(* ( + 1 3) 2) or simply * + 1 3 2
( * ( + 1 3) ( - 2 3)) or simply * + 1 3 - 2 3
Postfix form
Main Feature: the operator is after the two operands. Recursive definition
postfix-expression := (operand postfix-expression postfix-expression)
postfix-expression := atom
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 30
Recursive definition of classic version, without parentheses (we do not need them, because there is
no longer any ambiguity on how to match the operands to the operators):
postfix-expression := operand postfix-expression postfix-expression
postfix-expression := atom
Examples
(3 7 *) or simply 3 7 *
((1 3 + ) 2 *) or simply 1 3 + 2 *
((1 3 +) ( 2 3 -) * ) or simply 1 3 + 2 3 - *
b) Push and POP Algorithm.
A stack is an Abstract Data Type (ADT), commonly used in most programming languages. It is
named stack as it behaves like a real-world stack, for example – a deck of cards or a pile of plates,
etc.A real-world stack allows operations at one end only. For example, we can place or remove a
card or plate from the top of the stack only. Likewise, Stack ADT allows all data operations at one
end only. At any given time, we can only access the top element of a stack.
This feature makes it LIFO data structure. LIFO stands for Last-in-first-out. Here, the element
which is placed (inserted or added) last, is accessed first. In stack terminology, insertion operation
is called PUSH operation and removal operation is called POP operation.
Stack Representation
The following diagram depicts a stack and its operations −
A stack can be implemented by means of Array, Structure, Pointer, and Linked List. Stack can
either be a fixed size one or it may have a sense of dynamic resizing. Here, we are going to
implement stack using arrays, which makes it a fixed size stack implementation.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 31
Basic Operations
Stack operations may involve initializing the stack, using it and then de-initializing it. Apart from
these basic stuffs, a stack is used for the following two primary operations −
push() − Pushing (storing) an element on the stack.
pop() − Removing (accessing) an element from the stack.
When data is PUSHed onto stack.
To use a stack efficiently, we need to check the status of stack as well. For the same purpose, the
following functionality is added to stacks −
peek() − get the top data element of the stack, without removing it.
isFull() − check if stack is full.
isEmpty() − check if stack is empty.
At all times, we maintain a pointer to the last PUSHed data on the stack. As this pointer always
represents the top of the stack, hence named top. The top pointer provides top value of the stack
without actually removing it.
First we should learn about procedures to support stack functions −
peek()
Algorithm of peek() function −
begin procedure peek
return stack[top]
end procedure
Implementation of peek() function in C programming language −
Example
int peek() {
return stack[top];
}
isfull()
Algorithm of isfull() function −
begin procedure isfull
if top equals to MAXSIZE
return true
else
return false
endif
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 32
end procedure
Implementation of isfull() function in C programming language −
Example
bool isfull() {
if(top == MAXSIZE)
return true;
else
return false;
}
isempty()
Algorithm of isempty() function −
begin procedure isempty
if top less than 1
return true
else
return false
endif
end procedure
Implementation of isempty() function in C programming language is slightly different. We initialize
top at -1, as the index in array starts from 0. So we check if the top is below zero or -1 to determine
if the stack is empty. Here's the code −
Example
bool isempty() {
if(top == -1)
return true;
else
return false;
}
Push Operation
The process of putting a new data element onto stack is known as a Push Operation. Push operation
involves a series of steps −
Step 1 − Checks if the stack is full.
Step 2 − If the stack is full, produces an error and exit.
Step 3 − If the stack is not full, increments top to point next empty space.
Step 4 − Adds data element to the stack location, where top is pointing.
Step 5 − Returns success.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 33
If the linked list is used to implement the stack, then in step 3, we need to allocate space
dynamically.
Algorithm for PUSH Operation
A simple algorithm for Push operation can be derived as follows −
begin procedure push: stack, data
if stack is full
return null
endif
top ← top + 1
stack[top] ← data
end procedure
Implementation of this algorithm in C, is very easy. See the following code −
Example
void push(int data) {
if(!isFull()) {
top = top + 1;
stack[top] = data;
} else {
printf("Could not insert data, Stack is full.\n");
}
}
Pop Operation
Accessing the content while removing it from the stack, is known as a Pop Operation. In an array
implementation of pop() operation, the data element is not actually removed, instead top is
decremented to a lower position in the stack to point to the next value. But in linked-list
implementation, pop() actually removes data element and deallocates memory space.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 34
A Pop operation may involve the following steps −
Step 1 − Checks if the stack is empty.
Step 2 − If the stack is empty, produces an error and exit.
Step 3 − If the stack is not empty, accesses the data element at which top is pointing.
Step 4 − Decreases the value of top by 1.
Step 5 − Returns success.
Algorithm for Pop Operation
A simple algorithm for Pop operation can be derived as follows −
begin procedure pop: stack
if stack is empty
return null
endif
data ← stack[top]
top ← top - 1
return data
end procedure
Implementation of this algorithm in C, is as follows −
Example
int pop(int data) {
if(!isempty()) {
data = stack[top];
top = top - 1;
return data;
} else {
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 35
printf("Could not retrieve data, Stack is empty.\n");
}
}
7 ) What is a Binary Search Tree (BST) ? Make a BST for the following sequence of numbers
: 32, 68, 22, 95, 99, 26, 92, 84, 29, 36 Write Preorder, Inorder and Postorder Traversal
of this Tree.
Binary Search Tree | Set 1 (Search and Insertion)
The following is definition of Binary Search Tree(BST) according to Wikipedia
Binary Search Tree, is a node-based binary tree data structure which has the following properties:
The left subtree of a node contains only nodes with keys less than the node’s key.
The right subtree of a node contains only nodes with keys greater than the node’s key.
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.
Searching a key
To search a given key in Bianry Search Tree, we first compare it with root, if the key is present at
root, we return root. If key is greater than root’s key, we recur for right subtree of root node.
Otherwise we recur for left subtree.
// C function to search a given key in a given BST
struct node* search(struct node* root, int key)
{
// Base Cases: root is null or key is present at root
if (root == NULL || root->key == key)
return root;
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 36
// Key is greater than root's key
if (root->key < key)
return search(root->right, key);
// Key is smaller than root's key
return search(root->left, key);
}
Time Complexity: The worst case time complexity of search and insert 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).
Some Interesting Facts:
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 37
Inorder traversal of BST always produces sorted output.
We can construct a BST with only Preorder or Postorder or Level Order traversal. Note that
we can always get inorder traversal by sorting the only given traversal.
Number of unique BSTs with n distinct keys is Catalan Number
b) Explain the AVL Tree and Complete Binary Tree.
Ans:- Refer previous year solved solution paper.
8) What is threaded binary tree ?
Ans:- Refer previous year solved solution paper.
9) Write an algorithm for following (Any One) :–
i) BFS
(ii) DFS
Also discuss suitable example of it.
Ans:- Refer previous year solved solution paper.
10. (a) Define and explain following terminology of a graph as a data structure with example
:––
(i) Path and cycle.
A graph is a pictorial representation of a set of objects where some pairs of objects are connected by
links. The interconnected objects are represented by points termed as vertices, and the links that
connect the vertices are called edges.
Formally, a graph is a pair of sets (V, E), where V is the set of vertices and E is the set of edges,
connecting the pairs of vertices. Take a look at the following graph −
In the above graph,
V = {a, b, c, d, e}
E = {ab, ac, bd, cd, de}
Graph Data Structure
Mathematical graphs can be represented in data structure. We can represent a graph using an array
of vertices and a two-dimensional array of edges. Before we proceed further, let's familiarize
ourselves with some important terms −
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 38
Vertex − Each node of the graph is represented as a vertex. In the following example, the
labeled circle represents vertices. Thus, A to G are vertices. We can represent them using an
array as shown in the following image. Here A can be identified by index 0. B can be
identified using index 1 and so on.
Edge − Edge represents a path between two vertices or a line between two vertices. In the
following example, the lines from A to B, B to C, and so on represents edges. We can use a
two-dimensional array to represent an array as shown in the following image. Here AB can
be represented as 1 at row 0, column 1, BC as 1 at row 1, column 2 and so on, keeping other
combinations as 0.
Adjacency − Two node or vertices are adjacent if they are connected to each other through
an edge. In the following example, B is adjacent to A, C is adjacent to B, and so on.
Path − Path represents a sequence of edges between the two vertices. In the following
example, ABCD represents a path from A to D.
Basic Operations
Following are basic primary operations of a Graph −
Add Vertex − Adds a vertex to the graph.
Add Edge − Adds an edge between the two vertices of the graph.
Display Vertex − Displays a vertex of the graph.
B) Shortest Path Problem
Shortest paths.
An edge-weighted digraph is a digraph where we associate weights or costs with each edge. A
shortest path from vertex s to vertex t is a directed path from s to t with the property that no other
such path has a lower weight.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 39
Properties.
We summarize several important properties and assumptions.
Paths are directed. A shortest path must respect the direction of its edges.
The weights are not necessarily distances. Geometric intuition can be helpful, but the edge
weights weights might represent time or cost.
Not all vertices need be reachable. If t is not reachable from s, there is no path at all, and
therefore there is no shortest path from s to t.
Negative weights introduce complications. For the moment, we assume that edge weights
are positive (or zero).
Shortest paths are normally simple. Our algorithms ignore zero-weight edges that form
cycles, so that the shortest paths they find have no cycles.
Shortest paths are not necessarily unique. There may be multiple paths of the lowest weight
from one vertex to another; we are content to find any one of them.
Parallel edges and self-loops may be present. In the text, we assume that parallel edges are
not present and use the notation v->w to refer to the edge from v to w, but our code handles
them without difficulty.
Edge-weighted digraph data type.
We represent the weighted edges using the following API:
The from() and to() methods are useful for accessing the edge's vertices. DirectedEdge.java
implements this API.
We represent edge-weighted digraphs using the following API:
EdgeWeightedDigraph.java implements the API using the adjacency-lists representation.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 40
Data structures for single-source shortest paths.
Given an edge-weighted digraph and a designated vertex s, a shortest-paths tree (SPT) is a
subgraph containing s and all the vertices reachable from s that forms a directed tree rooted at s
such that every tree path is a shortest path in the digraph.
We represent the shortest paths with two vertex-indexed arrays:
Edges on the shortest-paths tree: edgeTo[v] is the the last edge on a shortest path from s to
v.
Distance to the source: distTo[v] is the length of the shortest path from s to v.
B) i)Hamilton Path.
Ans:- Refer previous year solved solution paper.
ii)Spanning Tree.
A spanning tree is a subset of Graph G, which has all the vertices covered with minimum possible
number of edges. Hence, a spanning tree does not have cycles and it cannot be disconnected..
By this definition, we can draw a conclusion that every connected and undirected Graph G has at
least one spanning tree. A disconnected graph does not have any spanning tree, as it cannot be
spanned to all its vertices.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 41
We found three spanning trees off one complete graph. A complete undirected graph can have
maximum nn-2 number of spanning trees, where n is the number of nodes. In the above addressed
example, 33−2 = 3 spanning trees are possible.
General Properties of Spanning Tree
We now understand that one graph can have more than one spanning tree. Following are a few
properties of the spanning tree connected to graph G −
A connected graph G can have more than one spanning tree.
All possible spanning trees of graph G, have the same number of edges and vertices.
The spanning tree does not have any cycle (loops).
Removing one edge from the spanning tree will make the graph disconnected, i.e. the
spanning tree is minimally connected.
Adding one edge to the spanning tree will create a circuit or loop, i.e. the spanning tree is
maximally acyclic.
Mathematical Properties of Spanning Tree
Spanning tree has n-1 edges, where n is the number of nodes (vertices).
From a complete graph, by removing maximum e - n + 1 edges, we can construct a
spanning tree.
A complete graph can have maximum nn-2 number of spanning trees.
Thus, we can conclude that spanning trees are a subset of connected Graph G and disconnected
graphs do not have spanning tree.
Application of Spanning Tree
Spanning tree is basically used to find a minimum path to connect all nodes in a graph. Common
application of spanning trees are −
Civil Network Planning
Computer Network Routing Protocol
Cluster Analysis
Let us understand this through a small example. Consider, city network as a huge graph and now
plans to deploy telephone lines in such a way that in minimum lines we can connect to all city
nodes. This is where the spanning tree comes into picture.
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 42
Minimum Spanning Tree (MST)
In a weighted graph, a minimum spanning tree is a spanning tree that has minimum weight than all
other spanning trees of the same graph. In real-world situations, this weight can be measured as
distance, congestion, traffic load or any arbitrary value denoted to the edges.
Minimum Spanning-Tree Algorithm
We shall learn about two most important spanning tree algorithms here −
Kruskal's Algorithm
Prim's Algorithm
Both are greedy algorithms.
11A)What is collision in hashing ? How can it be avoided ? What are the different collision
handling mechanisms ? Explain each with suitable example
Ans:- Refer previous year solved solution paper.
12) What is symbol table ? What are different data structures used for symbol table ? Discuss.
In computer science, a symbol table is a data structure used by a language translator such as a
compiler or interpreter, where each identifier in a program's source code is associated with
information relating to its declaration or appearance in the source.
Implementation
A common implementation technique is to use a hash table. A compiler may use one large symbol
table for all symbols or use separated, hierarchical symbol tables for different scopes. There are also
trees, linear lists and self-organizing lists which can be used to implement a symbol table. It also
simplifies the classification of literals in tabular format. The symbol table is accessed by most
phases of a compiler, beginning with the lexical analysis to optimization.
Uses
An object file will contain a symbol table of the identifiers it contains that are externally visible.
During the linking of different object files, a linker will use these symbol tables to resolve any
unresolved references.
A symbol table may only exist during the translation process, or it may be embedded in the output
of that process for later exploitation, for example, during an interactive debugging session, or as a
resource for formatting a diagnostic report during or after execution of a program.
While reverse engineering an executable, many tools refer to the symbol table to check what
addresses have been assigned to global variables and known functions. If the symbol table has been
stripped or cleaned out before being converted into an executable, tools will find it harder to
determine addresses or understand anything about the program.
At that time of accessing variables and allocating memory dynamically, a compiler should perform
many works and as such the extended stack model requires the symbol table.
Example
TGPCET/CSE/ Solution Set-W 17
DSPD Ms. Neha V. Mogre Page 43
Consider the following program written in C:
// Declare an external function
extern double bar(double x);
// Define a public function
double foo(int count)
{
double sum = 0.0;
// Sum all the values bar(1) to bar(count)
for (int i = 1; i <= count; i++)
sum += bar((double) i);
return sum;
}
A C compiler that parses this code will contain at least the following symbol table entries:
Symbol name Type Scope
bar function, double extern
x double function parameter
foo function, double global
count int function parameter
sum double block local
i int for-loop statement
In addition, the symbol table will also contain entries generated by the compiler for intermediate
expression values (e.g., the expression that casts the i loop variable into a double, and the return
value of the call to function bar()), statement labels, and so forth.
As another example, the symbol table of a small program is listed below. The table itself was
generated using the GNU binutils' nm utility. There is one data symbol, (noted by the "D" type),
and many functions (self defined as well as from the standard library). The first column is where the
symbol is located in the memory, the second is "The symbol type" and the third is the name of the
symbol. By passing suitable parameters, the symbol table was made to sort on basis of address.
Top Related