0% found this document useful (0 votes)
8 views

Data Structures

Uploaded by

mdsabeerali04
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views

Data Structures

Uploaded by

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

End-term Examination Sample Paper (Data Structures)

1. O(f) + O(g) is equal to ____________


a. O[max(f,g)] ✅
b. O[min(f,g)]
c. O(f*g)
d. Cannot be determined
2. Consider the following code :
public class Node {
int data;
Node a;
Node b;
}
Node defined in above code can be used for :
a. Binary Tree
b. Doubly linked List
c. Both a and b ✅
d. None of the above
3. Which of the following represents time taken by Binary Search correctly:
a. T(n) = T(n/2) + C ✅
b. T(n) = T(n-2) + C
c. T(n) = T(2n) + C
d. T(n) = T(n2) + C
4. Which of the recurrence relations can be solved using Master Theorem:
a. T(n) = T(n-1) + 2
b. T(n) = T(n/2) + T(n/2) + 1 ✅
c. T(n) = 1
d. T(n) = T(n2)
5. Analyze the complexity of following code snippet:
int n=20000,i = n;
while((--i)>=n){
// O(n) code
}
What will be the complexity of the above code
a. O(n)
b. O(n2)
c. O(1) ✅
d. O(20000)
6. Which of the following will throw EmptyStackException :
a. Number of elements in the stack is 0 and POP is attempted ✅
b. Number of elements in the stack is maximum and POP is attempted
c. Number of elements in the stack is 0 and PUSH is attempted
d. Number of elements in the stack is maximum and PUSH is
attempted
7. There exist two functions f(n) and g(n), such that for some constants c and
no the following holds
𝑓(𝑛) ≥ 𝑐. 𝑔(𝑛) ≥ 0 for all n≥n0
Which of the following represents above relationship:
a. g(n) = 𝝮(f(n))
b. f(n) = 𝚹(g(n))
c. f(n) = 𝝮(g(n)) ✅
d. g(n) = 𝚹(f(n))
8. You cannot create object of which of the following:
a. Stack<E>
b. Comparator<E> ✅
c. HashMap<E>
d. Hashtable<E>
9. Application of Queue can be seen where:
a. Elements are to be processed in the reverse order of their insertion
b. Elements are to be processed as per their natural ordering
c. Elements are to be processed in random order
d. Elements are to be processed in the order of their insertion ✅
10. Time complexities of inserting at the HEAD and TAIL of a doubly
linked list are _______________, respectively:
a. O(1) and O(n)
b. O(n) and O(1)
c. O(1) and O(1) ✅
d. O(n) and O(n)
11.The difference between peek() and remove() method of Queue interface
is:
a. peek() removes the element that was inserted first while remove()
removes the element that was inserted last
b. peek() removes the element inserted last while remove() removes
the element that was inserted first
c. There is no difference between the two
d. peek() allows us to look at the FRONT element without removing
while remove() actually removes the element ✅
12. The difference between poll() and remove() of Queue<E> interface is:
a. poll() returns null if the queue is empty while remove() throws a
NoSuchElementException ✅
b. remove() returns null if the queue is empty while poll() throws a
NoSuchElementException
c. poll() does not remove any element form the queue while remove()
does
d. None of the above
13. Which of the following refers to implementation of a STACK using
QUEUE by making POP operation costly:
a. POP = DEQUEUE OPERATION in the QUEUE and TOP of the
STACK is SAME as REAR of the QUEUE
b. PUSH = ENQUEUE OPERATION in the QUEUE and TOP of the
STACK is SAME as FRONT of the QUEUE
c. POP = DEQUEUE OPERATION in the QUEUE and TOP of the
STACK is SAME as FRONT of the QUEUE
d. PUSH = ENQUEUE OPERATION in the QUEUE and TOP of the
STACK is SAME as REAR of the QUEUE ✅
14. Which of the following is correct about HashMap
a. It uses a default Load Factor of 0.75 ✅
b. It is an interface in collections package
c. It is a class in collections package
d. It is synchronized
15. Which of the following is correctly matched in the context of collision
handling mechanism:
a. Separate Chaining = Open addressing
b. Linear Probing = Open Hashing
c. Open addressing = Open Hashing
d. Separate Chaining = Open Table ✅

16. Which of the following is NOT a characteristic of a good hash function?


a. It should avoid collisions
b. It should be fast to compute
c. It should uniformly distribute the keys in the bucket array
d. It should be a polynomial function ✅
17. Which of the following is an interface in Java:
a. Hashtable
b. HashMap
c. HashSet
d. Map ✅
18. Select the correct HashMap declaration for efficiently solving First
Unique Character problem:
a. HashMap<char, int> char_freq = new HashMap<>();
b. HashMap<Character, Double> char_freq = new HashMap<>();
c. HashMap<Integer, Character> char_freq = new
HashMap<>();
d. HashMap<Character, Integer> char_freq = new
HashMap<>(); ✅
19. Which of the following methods is used to insert keys into the
HashMap<K,V>?
a. put(K key, V value) ✅
b. put(K key)
c. put(V key, K value)
d. put(V value)
20. Complexity of searching an element in the map that uses separate
chaining depends on:
a. How uniformly elements are distributed using the Hash function ✅
b. How many keys are to be mapped
c. How many keys are null
d. None of the above
21. Which of the following will cause NullPointerException:
a. map.put(null, 2) when map is a reference of type
HashMap<Integer,Integer>
b. table.put(2,4) when table is a reference of type
Hashtable<Integer,Integer>
c. table.put(null,2) when table is a reference of type
Hashtable<Integer,Integer> ✅
d. map.put(2,null) when map is a reference of type
HashMap<Integer,Integer>

22. Select the correct statement:


a. A heap is a full binary tree
b. Every complete binary tree is a full binary tree

c. Every perfect binary tree is a full binary tree
d. Every full binary tree is a perfect binary tree
23. PriorityQueue class does not implement which of the following interface:
a. List
b. Queue
c. Iterable
d. Collection ✅
24. Arrays are used to implement Heaps. The reason for this is ________
a. Heap is a perfect binary tree
b. Heap has minimum or maximum value at the root
c. Heap has all levels completely field and last level has all nodes as
left as possible ✅
d. None of the above
25. Heap sort has O(nlog n) complexity because
a. Number of nodes to be heapified depends on n and heapifying takes
log n time. ✅
b. Heapification for any node takes O(nlog n) time. This is the
combined complexity for all the nodes
c. Both
d. None of the above
26. Median of a stream of integers exploits which property of median?
a. Median requires sorting of elements
b. Median is maximum value of lesser half or minimum value of greater
half or average of both, if elements are sorted ✅
c. Median requires adding of elements
d. Median requires extremes of a list of integers to have constant
difference

27. Consider the following graph

Correct topological sort for the given graph is:


a. 0 → 1 → 2 → 3 ✅
b. 0 → 3 → 2 → 1
c. 3 → 2 → 1 → 0
d. 2 → 0 → 1 → 3
28. BFS of following graph will be:

What will be the BFS for the above graph? (Start from 0 and use
natural order of labels to select neighbors to visit)
a. 0, 1, 2, 3, 4, 5, 6, 7, 8

b. 0, 1, 2, 3, 4, 7, 8, 6, 5
c. 0, 1, 3, 6, 5, 8, 7, 2, 4
d. None of the above
29. Consider the following matrix for a Weighted Directed Graph

The shortest path from A to F has the cost/length:


a. 1
b. 3
c. 12 ✅
d. 15
30. Floyd Warshall algorithm is an example of
a. All node Shortest Path Algorithm ✅
b. Single Source Shortest Path Algorithm
c. Single edge shortest path algorithm
d. Cyclic shortest path algorithm
31. Bellman Ford Algorithm is slower than Dijkstra’s Algorithm but ______
a. It can compute shortest path for every pair of vertices
b. It can handle cycles which Dijkstra’ Algorithm cannot
c. It can handle negative weights ✅
d. It focuses on edges
32. If we don’t use Priority Queue (min heap) in Dijkstra then
a. Complexity is O(V2) ✅
b. Complexity is O(V+ElogV)
c. Complexity is O(V)
d. Complexity is O(log V)
Descriptive Questions (Sample)

1. Write a pseudocode to solve parenthesis matching


problem using a stack.
Ans. The parenthesis matching problem is a common problem in computer science

and programming. It involves determining whether a given expression that


contains various types of parentheses, such as round brackets '()', square
brackets '[]', and curly braces '{}', is properly balanced and well-formed. In other
words, the problem is to check if all opening parentheses have corresponding
closing parentheses in the correct order, with no unmatched or misordered pairs.

Following is the pseudocode for solving the above problem :

Function isParenthesisMatching(input_string):
// Create an empty stack to store opening parentheses
Stack stack

// Loop through each character in the input string


For each character in input_string:
If character is an opening parenthesis (e.g., '(', '[', or '{'):
// Push it onto the stack
stack.push(character)
Else if character is a closing parenthesis (e.g., ')', ']', or
'}'):
// If the stack is empty, return false (mismatched
parenthesis)
If stack.isEmpty():
return false
Else:
// Pop the top element from the stack
top = stack.pop()
// Check if the popped opening parenthesis matches the
current closing parenthesis
If not isMatchingPair(top, character):
return false

// After processing the entire string, if the stack is empty, return


true (all parentheses are matched)
If stack.isEmpty():
return true
Else:
// If there are unmatched opening parentheses left in the stack,
return false
return false

Function isMatchingPair(opening, closing):


// Check if the opening and closing parentheses form a matching pair
return (opening is '(' and closing is ')') or
(opening is '[' and closing is ']') or
(opening is '{' and closing is '}')

2. What is an Abstract Data Type?


Ans. An abstract data type (ADT) is a high-level description of a collection of data and

a set of operations that can be performed on that data. It defines the behavior of
a data structure, including how data is stored and how operations are performed
on it, without specifying the implementation details. In other words, an ADT
abstracts the data and its associated operations, providing a clear interface for
interacting with the data while hiding the underlying implementation.

Key characteristics of abstract data types include:


​ Encapsulation: ADTs encapsulate both data and the operations that can
be performed on that data, allowing the internal details of the data
structure to remain hidden.
​ Data Abstraction: ADTs define what data is stored and what operations
can be performed on it, abstracting away the underlying data
representation.
​ Information Hiding: ADTs provide a well-defined interface, hiding the
implementation details and ensuring that users of the ADT only interact
with it through specified methods and operations.
​ Reusability: ADTs promote code reuse because they allow developers to
create and use data structures without having to re-implement them from
scratch.

Common examples of abstract data types include:

​ Stack: An abstract data type that represents a last-in, first-out (LIFO) data
structure with operations like push and pop.
​ Queue: An abstract data type that represents a first-in, first-out (FIFO) data
structure with operations like enqueue and dequeue.
​ List: An abstract data type that represents a linear collection of elements
with operations for adding, removing, and accessing elements.
​ Set: An abstract data type that represents a collection of unique elements
with operations for adding, removing, and checking for membership.
​ Dictionary or Map: An abstract data type that stores key-value pairs and
allows operations for inserting, retrieving, and deleting values associated
with keys.
​ Graph: An abstract data type for modeling graphs with vertices and edges,
often with various graph traversal and manipulation operations.

​ It's important to note that while ADTs define the behavior and interface of
a data structure, the actual implementation may vary.
​ Different programming languages and libraries may provide different
implementations of the same ADT, but as long as they conform to the
specified interface and behavior, they can be used interchangeably. This
separation of the abstract interface from the concrete implementation is a
fundamental concept in computer science and software engineering,
promoting modularity, code reuse, and maintainability.

3. How is collision handling typically addressed in hashing,


and what are some common collision resolution
techniques?
Ans. In hashing, collisions occur when two different keys or data items hash to the

same location (i.e., they produce the same hash value) in the hash table.
Collisions are common in practice, and addressing them is essential to ensure
that hash tables function correctly. There are several common collision
resolution techniques:

​ Open Addressing (Probing): In open addressing, when a collision occurs, the


algorithm searches for the next available slot in the hash table. There are various
probing strategies, such as linear probing (search for the next empty slot),
quadratic probing (search with an increment that grows quadratically), and
double hashing (use a secondary hash function to determine the next slot). Open
addressing methods attempt to find an empty slot in the same table where the
collision occurred.
​ Separate Chaining: In separate chaining, each slot in the hash table is associated
with a linked list or another data structure. When a collision happens, the new
item is simply added to the linked list at that slot. This approach allows multiple
items to coexist at the same location and is more forgiving of collisions. It's
essential to choose a good data structure for the chains, such as a linked list or a
dynamic array, to ensure efficient operations.
​ Cuckoo Hashing: Cuckoo hashing is a method where each key is hashed to two
separate locations. If there is a collision in either location, one of the keys is
"kicked out" to its alternative location. This process may recursively continue until
no more collisions occur. Cuckoo hashing can be efficient but requires careful
implementation to avoid infinite loops.
​ Robin Hood Hashing: In Robin Hood hashing, collisions are resolved by
comparing the "probe length," which is the distance between the initial hashed
location and the collision location. If a new item has a shorter probe length than
the existing item, it "takes" the slot, and the existing item moves to the next
available slot. This approach aims to minimize the maximum probe length and
improve average case performance.
​ Double Hashing: Double hashing is a variation of open addressing where a
secondary hash function is used to calculate the step size for probing when a
collision occurs. It helps spread out items more evenly in the hash table, reducing
the likelihood of collisions.

The choice of collision resolution technique depends on the specific


requirements and constraints of the application. Each method has its own
advantages and disadvantages in terms of time complexity, space efficiency, and
ease of implementation. The key is to choose an appropriate technique that
minimizes collisions and optimizes the overall performance of the hash table for
a given use case.

Collision Resolution in Java with example of HashMap/Hashtable


Prior to Java 8, HashMap and all other hash table based Map implementation
classes in Java handle collision by chaining, i.e. they use linked list to store map
entries which ended in the same bucket due to a collision. If a key end up in the
same bucket location where entry is already stored then this entry is just added
at the head of the linked list there. In the worst case this degrades the
performance of the get() method of HashMap to O(n) from O(1). In order to
address this issue in the case of frequent HashMap collisions, Java 8 has started
using a balanced tree along with the linked list for storing collided entries. This
also means that in the worst case you will get a performance boost from O(n) to
O(log n)

The threshold of switching to the balanced tree is defined as


TREEIFY_THRESHOLD constant in java.util.HashMap JDK 8 code. Currently, its
values are 8, which means if there are more than 8 elements in the same bucket
then HashMap will use a tree instead of a linked list to hold them in the same
bucket.

4. How do AVL trees work, and what are the principles and
balancing criteria that ensure that an AVL tree maintains
its balanced and self-balancing properties during
insertions and deletions?
Ans. AVL trees, named after their inventors Adelson-Velsky and Landis, are a type of
self-balancing binary search tree. They are designed to maintain a balanced
structure, which ensures efficient O(log n) time complexity for common
operations such as searching, insertion, and deletion.
The key principles and balancing criteria that ensure an AVL tree's balance
during insertions and deletions are as follows:

Balancing Condition: In an AVL tree, for every node, the heights of its left and
right subtrees (the balance factor) can differ by at most 1. This condition
ensures that the tree remains approximately balanced.

Balancing Operations:

When an element is inserted into an AVL tree, the tree may become
unbalanced due to the insertion. To restore balance, one or more rotations
are performed on affected nodes.

There are four possible types of rotations:

1. Left-rotation
2. Right-rotation
3. Left-right rotation
4. Right-left rotation.

These rotations maintain the balancing condition.

Recursiveness: Balancing of AVL trees is a recursive process. When a node is


inserted or deleted, the balance factor of its ancestors up to the root is checked,
and rotations are performed if necessary to restore balance.
Height Updating: After insertion or deletion, the height of a node's subtree is
updated. The balance factor is calculated as the height of the right subtree minus
the height of the left subtree. If this balance factor exceeds 1 or -1, the tree is
unbalanced, and rotations are performed.

Double Rotation: In some cases, a single rotation may not be sufficient to restore
balance. For example, after a left child of a node becomes taller than its right
child, a right rotation may be applied to the parent node. If this, in turn, makes the
left child of the parent node taller than its right child, a left rotation is applied to
the grandparent node. This is called a double rotation and is used to restore
balance.

Deletion Balancing: After deleting a node from an AVL tree, the same balancing
criteria are applied. Deletion may also lead to imbalance, and the same rotation
techniques are used to maintain balance.

The self-balancing property of AVL trees ensures that the height of the tree
remains logarithmic, which, in turn, guarantees efficient search, insertion, and
deletion operations. The balancing criteria are rigorously enforced during tree
modification to maintain this balance, making AVL trees a popular choice for
data structures where fast and reliable access is essential.

5. Explain insertion to an AVL with the help of an example


Ans. An AVL tree is a self-balancing binary search tree where the balance factor of
every node (the height of the left subtree minus the height of the right subtree) is
maintained to be at most 1. If the balance factor exceeds 1 or -1, rotations are
performed to restore balance.

Suppose we have the following AVL tree:

We want to insert the value 4 into this tree. Here's how the insertion process
works:

1. Normal Binary Search Tree (BST) Insertion:

First, insert the element 12 into the AVL tree as you would in a
regular binary search tree, following the order of the tree:
2. Update Heights: After inserting the element, update the heights of the
nodes from the newly inserted node up to the root:

3. Check Balance and Perform Rotations: Check the balance factor of each
node along the path from the inserted node up to the root. In this case, we
need rebalancing because starting from Node 10 the balancing factors
are:

Node 10 needs a RIGHT ROTATION (new node is added to the left subtree
of left subtree of unbalanced node or node 10)
The insertion process in an AVL tree ensures that the tree maintains its balanced
structure, even after inserting new elements. Rotations are used to correct any
imbalance that may arise during the insertion, and the AVL property is
consistently enforced, ensuring efficient operations in the tree.

6. Compare the performance of following operations when


using Adjacency list, Edge List and Adjacency Matrix:
1. Add New Node
2. Add New Edge
3. Remove Edge

Ans. The performance of various operations in graph representations, such as


Adjacency List, Edge List, and Adjacency Matrix, depends on the specific
operation and the characteristics of the graph. Here's a comparison of the
mentioned operations:

1. Add New Node


a. Adjacency List: Adding a new node is generally efficient in an
adjacency list. You create a new list or array to represent the node
and update the lists of its neighbors. The time complexity is O(1) on
average.
b. Edge List: Adding a new node to an edge list typically involves
adding a new record for the node. This operation is straightforward
and has a time complexity of O(1).
c. Adjacency Matrix: Adding a new node to an adjacency matrix is not
efficient, as it requires expanding the matrix to accommodate the
new node. This often involves copying the entire matrix to a larger
one, resulting in a time complexity of O(V^2), where V is the number
of nodes.
2. Add New Edge:
a. Adjacency List: Adding a new edge in an adjacency list is generally
efficient. You add the edge to the adjacency list of the source node,
which usually involves appending a node to a linked list. The time
complexity is O(1) on average.
b. Edge List: Adding a new edge to an edge list is straightforward and
has a time complexity of O(1).
c. Adjacency Matrix: Adding a new edge in an adjacency matrix is
efficient; you update the corresponding entry in the matrix. The time
complexity is O(1).
3. Remove Edge:
a. Adjacency List: Removing an edge from an adjacency list is
efficient. You remove the edge from the adjacency list of the source
node. The time complexity is O(degree of the source node).
b. Edge List: Removing an edge from an edge list is also efficient. You
can locate the edge and remove it with a time complexity of O(E),
where E is the number of edges.
c. Adjacency Matrix: Removing an edge from an adjacency matrix is
straightforward and has a time complexity of O(1).

In summary, the choice of graph representation affects the performance of


these operations differently. Adjacency lists are generally more efficient for
adding and removing nodes and edges and are particularly well-suited for sparse
graphs. Edge lists are simple and efficient for adding and removing edges.
Adjacency matrices are efficient for certain operations but may not be ideal for
dynamic graphs or graphs with many nodes and few edges. The choice of
representation should consider the specific graph characteristics and the type
of operations you need to perform most frequently.

You might also like