100% found this document useful (1 vote)
26 views

Data Structures (KCS301)

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
26 views

Data Structures (KCS301)

Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

B.

TECH

(SEM III) THEORY EXAMINATION 2020-21

DATA STRUCTURES

Time: 3 Hours Total Marks: 100


Section-A
1 a. Define time space trade-off.
Ans: A tradeoff is a situation where one thing increases and another thing decreases. It is a
way to solve a problem in:
 Either in less time and by using more space, or
 In very little space by spending a long amount of time.

Types of Space-Time Trade-off


 Compressed or Uncompressed data
 Re Rendering or Stored images
 Smaller code or loop unrolling
 Lookup tables or Recalculation

1 b. Differentiate array and linked list.


Ans: The following are some of the differences between Arrays and Linked Lists:

Arrays Linked Lists

Linked List is an ordered collection of elements


An array is a collection of elements of a
of the same type in which each element is
similar data type.
connected to the next using pointers.

Random accessing is not possible in linked lists.


Array elements can be accessed
The elements will have to be accessed
randomly using the array index.
sequentially.

New elements can be stored anywhere and a


Data elements are stored in contiguous
reference is created for the new element using
locations in memory.
pointers.

Insertion and Deletion operations are


Insertion and Deletion operations are fast and
costlier since the memory locations are
easy in a linked list.
consecutive and fixed.

1 c. Explain tail recursion with suitable example.


In computer science, a tail call is a subroutine call performed as the final action of a
procedure. If the target of a tail is the same subroutine, the subroutine is said to be tail-
recursive, which is a special case of direct recursion. Tail recursion (or tail-end recursion)
is particularly useful, and often easy to handle optimization in implementations.

function foo(data) {
a(data);
return b(data);
}

1d. write the full and empty condition for circular queue data structure

Ans: In a Linear queue, once the queue is completely full, it's not possible to insert more
elements. Even if we dequeue the queue to remove some of the elements, until the queue is
reset, no new elements can be inserted. You must be wondering why?

1 e. Examine the minimum number of interchanges needed to convert the array


90,20,41,18,13,11,3 ,6,8,12,7,71,99 into a maximum heap.
Ans: swap(11,71), swap(71,41),swap(41,99),swap(71,99),swap(90,91)
Hence 5 interchange are required.
1f. Differentiate sequential search and binary search.
Ans: Comparison of Searching methods in Data Structures

Sequential Search Binary Search

Finds the key present at first position in constant Finds the key present at center position in
time constant time

Sequence of elements in the container does not


The elements must be sorted in the container
affect.

1g.
1h. Write shot notes on adjacency multi list representation a graph.
Ans: An edge in an undirected graph is represented by two nodes in adjacency list
representation. Adjacency Multi lists: lists in which nodes may be shared among several lists.
1i. What is the importance of threaded binary tree?
Ans: Inorder traversal of a Binary tree can either be done using recursion or with the use of
a auxiliary stack. The idea of threaded binary trees is to make inorder traversal faster and
do it without stack and without recursion. A binary tree is made threaded by making all
right child pointers that would normally be NULL point to the inorder successor of the
node (if it exists).
There are two types of threaded binary trees.
Single Threaded: Where a NULL right pointers is made to point to the inorder successor (if
successor exists)
Double Threaded: Where both left and right NULL pointers are made to point to inorder
predecessor and inorder successor respectively. The predecessor threads are useful for
reverse inorder traversal and postorder traversal.
The threads are also useful for fast accessing ancestors of a node.
Following diagram shows an example Single Threaded Binary Tree. The dotted lines
represent threads.

1j. Write short notes on min heap.


Ans: A Binary Heap is a Binary Tree with following properties.
1) It’s a complete tree (All levels are completely filled except possibly the last level and the
last level has all keys as left as possible). This property of Binary Heap makes them suitable
to be stored in an array.
2) A Binary Heap is either Min Heap or Max Heap. In a Min Binary Heap, the key at root
must be minimum among all keys present in Binary Heap. The same property must be
recursively true for all nodes in Binary Tree. Max Binary Heap is similar to MinHeap.
Examples of Min Heap:
10 10
/ \ / \
20 100 15 30
/ / \ / \
30 40 50 100 40

Section B
2a. Consider a multi-dimensional array Array[90][30][40] with base address starts at
1000. Calculate the address of A[10][20][30] in row major order and column major
order. Assume the first element is stored at A[2][2][2] and each element take 2 byte.
Ans 2C: Hash table is a data structure in which keys are mapped to array positions by a hash
function.
Hash table, an element with key k is stored at index h(k) and not k.
It means a hash function h is used to calculate the index at which the element with key k will
be stored.
Hash table in which each key from the set k is mapped to locations generated by using a hash
function.
When two or more keys map to same memory location is known as collision.
The process of mapping the keys to appropriate locations in a hash table is called hashing.
Different Hash Functions:
1. Division Method
2. Multiplication method
3. Mid Square Method
4. Folding Method
Division Modulo Method
• It is the simplest method of hashing an integer k.
• The method divides k by M and then uses the remainder thus obtained.
• h(k)= k mod M
Where k is the key and M is the Size of the hash table.
Multiplication Method:
1. Choose a constant A such that 0 < A <1.
2. Multiply the key k by A.
3. Extract the fractional part of kA.
4. Multiply the result of step 3 by m and take the floor.
h(k) = |m (kA mod 1) |
Mid-Square Method:
1. Square the value of the key. i.e. k2.
2. Extract the middle r bits of the result obtained in step 1.
h(k) = k2

2d. Graph Traversal Algorithm

In this part of the tutorial we will discuss the techniques by using which, we can traverse all
the vertices of the graph.

Traversing the graph means examining all the nodes and vertices of the graph. There are two
standard methods by using which, we can traverse the graphs. Lets discuss each one of them
in detail.

o Breadth First Search


o Depth First Search

Breadth First Search (BFS) Algorithm

Breadth first search is a graph traversal algorithm that starts traversing the graph from root
node and explores all the neighbouring nodes. Then, it selects the nearest node and explore all
the unexplored nodes. The algorithm follows the same process for each of the nearest node
until it finds the goal.

The algorithm of breadth first search is given below. The algorithm starts with examining the
node A and all of its neighbours. In the next step, the neighbours of the nearest node of A are
explored and process continues in the further steps. The algorithm explores all neighbours of
all the nodes and ensures that each node is visited exactly once and no node is visited twice.

Algorithm
o Step 1: SET STATUS = 1 (ready state)
for each node in G
o Step 2: Enqueue the starting node A
and set its STATUS = 2
(waiting state)
o Step 3: Repeat Steps 4 and 5 until
QUEUE is empty
o Step 4: Dequeue a node N. Process it
and set its STATUS = 3
(processed state).
o Step 5: Enqueue all the neighbours of
N that are in the ready state
(whose STATUS = 1) and set
their STATUS = 2
(waiting state)
[END OF LOOP]
o Step 6: EXIT

Example

Consider the graph G shown in the following image, calculate the minimum path p from node
A to node E. Given that each edge has a length of 1.
Solution:

Minimum Path P can be found by applying breadth first search algorithm that will begin at
node A and will end at E. the algorithm uses two queues,
namely QUEUE1 and QUEUE2. QUEUE1 holds all the nodes that are to be processed
while QUEUE2 holds all the nodes that are processed and deleted from QUEUE1.

Lets start examining the graph from Node A.

1. Add A to QUEUE1 and NULL to QUEUE2.

1. QUEUE1 = {A}
2. QUEUE2 = {NULL}

2. Delete the Node A from QUEUE1 and insert all its neighbours. Insert Node A into QUEUE2

1. QUEUE1 = {B, D}
2. QUEUE2 = {A}

3. Delete the node B from QUEUE1 and insert all its neighbours. Insert node B into QUEUE2.

1. QUEUE1 = {D, C, F}
2. QUEUE2 = {A, B}

4. Delete the node D from QUEUE1 and insert all its neighbours. Since F is the only neighbour
of it which has been inserted, we will not insert it again. Insert node D into QUEUE2.

1. QUEUE1 = {C, F}
2. QUEUE2 = { A, B, D}

5. Delete the node C from QUEUE1 and insert all its neighbours. Add node C to QUEUE2.

1. QUEUE1 = {F, E, G}
2. QUEUE2 = {A, B, D, C}

6. Remove F from QUEUE1 and add all its neighbours. Since all of its neighbours has already
been added, we will not add them again. Add node F to QUEUE2.

1. QUEUE1 = {E, G}
2. QUEUE2 = {A, B, D, C, F}

7. Remove E from QUEUE1, all of E's neighbours has already been added to QUEUE1
therefore we will not add them again. All the nodes are visited and the target node i.e. E is
encountered into QUEUE2.
1. QUEUE1 = {G}
2. QUEUE2 = {A, B, D, C, F, E}

Now, backtrack from E to A, using the nodes available in QUEUE2.

The minimum path will be A → B → C → E.

2e.

3 b. write a c program to insert a node at kth position in single linked-list


Algorithm for C Program for inserting at the nth node of the Singly Linked List:-
STEP 1: IF ptr = NULL
Write Overflow
Goto STEP 12
End Of IF

STEP 2: SET new_node =ptr

STEP 3: new_node → data

STEP 4: SET temp = head

STEP 5: SET I = 0

STEP 6: REPEAT STEP 5 AND 6 UNTIL I

STEP 7: temp = temp → next

STEP 8: IF temp = NULL

Write desired node not found


Goto STEP 12
End Of IF
End Of LOOP

STEP 9: ptr → next = temp → next

STEP 10: temp → next=ptr

STEP 11: SET ptr=new_node

STEP 12: EXIT

C Program for insertion at the nth node of the Singly Linked List:-
#include <stdio.h>
#include <stdlib.h>
struct node *head=NULL;
struct node
{
int data;
struct node *next;
};

void ins(int data)


{
struct node *temp = (struct node*)malloc(sizeof(struct node)); //it will insert a new
node to the start of the linked list
temp->data=data;
temp->next=head;
head=temp;
}

void ins_at_pos_n(int data,int position)


{
struct node *ptr = (struct node*)malloc(sizeof(struct node));
ptr->data=data; //Creating a new node
int i;
struct node *temp=head;
if(position==1)
{
ptr->next=temp;
head=ptr;
return;
}

for(i=1;i<position-1;i++) //moving to the (n-1)th position node in the linked list


{
temp=temp->next;
}

ptr->next=temp->next; //Make the newly created node point to next node of ptr temp
temp->next=ptr; //Make ptr temp point to newly created node in the linked list
}

void display()
{
struct node *temp=head;
printf("\nList: ");
while(temp!=NULL)
{
printf("\n%d ",temp->data);
temp=temp->next;
}
}

int main()
{
int i, n, pos, data;
printf("Enter the number of nodes: \n");
scanf("%d",&n);
printf("Enter the data for the nodes: \n");
for(i=0;i<n;i++)
{
scanf("%d",&data);
ins(data);
}
printf("Enter the data you want to insert in between the nodes: \n");
scanf("%d",&data);
printf("Enter the position at which you want to insert the nodes: \n");
scanf("%d",&pos);
if(pos>n)
{
printf("Enter a valid position: ");

}
else
{
ins_at_pos_n(data,pos);

}
display();
return 0;
}
Output:-
Enter the number of nodes:
5
Enter the data for the nodes:
44
5
22
6
95
Enter the data you want to insert in between the nodes:
100
Enter the position at which you want to insert the nodes:
4
List:
44
5
22
100
6
95

4 b. Write a C program to implement stack using single linked-list.

#include<stdio.h>
#include<stdlib.h>

/* Structure to create a node with data and pointer */

struct Node
{
int data;
struct Node *next;
}*top = NULL; // Initially the list is empty

void push(int);
void pop();
void display();

int main()
{
int choice, value;
printf("\nIMPLEMENTING STACKS USING LINKED LISTS\n");
while(1){
printf("1. Push\n2. Pop\n3. Display\n4. Exit\n");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1: printf("\nEnter the value to insert: ");
scanf("%d", &value);
push(value);
break;

case 2: pop();
break;

case 3: display();
break;

case 4: exit(0);
break;
default: printf("\nInvalid Choice\n");
}}}

void push(int value)


{
struct Node *newNode;
newNode = (struct Node*)malloc(sizeof(struct Node));
newNode->data = value; // get value for the node
if(top == NULL)
newNode->next = NULL;
else
newNode->next = top; // Make the node as TOP
top = newNode;
printf("Node is Inserted\n\n");
}

void pop()
{
if(top == NULL)
printf("\nEMPTY STACK\n");
else{
struct Node *temp = top;
printf("\nPopped Element : %d", temp->data);
printf("\n");
top = temp->next; // After popping, make the next node as TOP
free(temp);
}}

void display()
{
// Print the stack
if(top == NULL)
printf("\nEMPTY STACK\n");
else
{
printf("The stack is \n");
struct Node *temp = top;
while(temp->next != NULL){
printf("%d--->",temp->data);
temp = temp -> next;
}
printf("%d--->NULL\n\n",temp->data);
}}

5a. Write an algorithm for merge sort and apply on following elements
45,32,65,76,23,12,54,67,22,87
Ans: Algorithm for Merge Sort:
Merge sort is one of the most efficient sorting algorithms. It works on the principle of Divide
and Conquer. Merge sort repeatedly breaks down a list into several sublists until each sublist
consists of a single element and merging those sublists in a manner that results into a sorted
list.
Merge sort is a sorting technique based on divide and conquer technique. With worst-case
time complexity being Ο(n log n), it is one of the most respected algorithms.
Merge sort first divides the array into equal halves and then combines them in a sorted manner.
How Merge Sort Works?
To understand merge sort, we take an unsorted array as the following −

We know that merge sort first divides the whole array iteratively into equal halves unless the
atomic values are achieved. We see here that an array of 8 items is divided into two arrays of
size 4.

This does not change the sequence of appearance of items in the original. Now we divide these
two arrays into halves.

We further divide these arrays and we achieve atomic value which can no more be divided.

Now, we combine them in exactly the same manner as they were broken down. Please note
the color codes given to these lists.
We first compare the element for each list and then combine them into another list in a sorted
manner. We see that 14 and 33 are in sorted positions. We compare 27 and 10 and in the target
list of 2 values we put 10 first, followed by 27. We change the order of 19 and 35 whereas 42
and 44 are placed sequentially.

In the next iteration of the combining phase, we compare lists of two data values, and merge
them into a list of found data values placing all in a sorted order.
After the final merging, the list should look like this −

Now we should learn some programming aspects of merge sorting.

Algorithm

Merge sort keeps on dividing the list into equal halves until it can no more be divided. By
definition, if it is only one element in the list, it is sorted. Then, merge sort combines the
smaller sorted lists keeping the new list sorted too.
Step 1 − if it is only one element in the list it is already sorted, return.
Step 2 − divide the list recursively into two halves until it can no more be divided.
Step 3 − merge the smaller lists into new list in sorted order.

5 b. Write a c program for index sequential search


// C program for Indexed Sequential Search
#include <stdio.h>
#include <stdlib.h>

void indexedSequentialSearch(int arr[], int n, int k)


{
int elements[20], indices[20], temp, i, set = 0;
int j = 0, ind = 0, start, end;
for (i = 0; i < n; i += 3) {

// Storing element
elements[ind] = arr[i];

// Storing the index


indices[ind] = i;
ind++;
}
if (k < elements[0]) {
printf("Not found");
exit(0);
}
else {
for (i = 1; i <= ind; i++)
if (k <= elements[i]) {
start = indices[i - 1];
end = indices[i];
set = 1;
break;
}
}
if (set == 0) {
start = indices[i - 1];
end = n;
}
for (i = start; i <= end; i++) {
if (k == arr[i]) {
j = 1;
break;
}
}
if (j == 1)
printf("Found at index %d", i);
else
printf("Not found");
}

// Driver code
void main()
{

int arr[] = { 6, 7, 8, 9, 10 };
int n = sizeof(arr) / sizeof(arr[0]);

// Element to search
int k = 8;
indexedSequentialSearch(arr, n, k);
}

You might also like