0% found this document useful (0 votes)
19 views33 pages

Module-3 Q&a

Module3 opertional amplifier with study materia noyes

Uploaded by

Vikesh Kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
19 views33 pages

Module-3 Q&a

Module3 opertional amplifier with study materia noyes

Uploaded by

Vikesh Kumar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 33

QUESTIONS COs RBT Mar

Levels ks
Module-3

1) Write a C++ function to perform the insert and delete operation of the queue
using arrays.
#include <iostream>
using namespace std;
int queue[100], n = 100, front = - 1, rear = - 1;
void Insert() {
int val;
if (rear == n - 1)
cout<<"Queue Overflow"<<endl;
else {
if (front == - 1)
front = 0;
cout<<"Insert the element in queue : "<<endl;
cin>>val;
rear++;
queue[rear] = val;
}
}
void Delete() {
if (front == - 1 || front > rear) {
cout<<"Queue Underflow ";
CO3 L2 10M
return ;
} else {
cout<<"Element deleted from queue is : "<< queue[front] <<endl;
front++;;
}
}
void Display() {
if (front == - 1)
cout<<"Queue is empty"<<endl;
else {
cout<<"Queue elements are : ";
for (int i = front; i <= rear; i++)
cout<<queue[i]<<" ";
cout<<endl;
}
}
int main() {
int ch;
cout<<"1) Insert element to queue"<<endl;
cout<<"2) Delete element from queue"<<endl;
cout<<"3) Display all the elements of queue"<<endl;
cout<<"4) Exit"<<endl;
do {
cout<<"Enter your choice : "<<endl;
cin>>ch;
switch (ch) {
case 1: Insert();
break;
case 2: Delete();
break;
case 3: Display();
break;
case 4: cout<<"Exit"<<endl;
break;
default: cout<<"Invalid choice"<<endl;
}
} while(ch!=4);
return 0;
}

The provided C++ program simulates queue operations (insert, delete, and
display). If we input the values 10, 20, 30, 40, 50 through the "Insert"
option, the queue operates as follows:

Step-by-Step Input and Output:

Menu:

1) Insert element to queue


2) Delete element from queue
3) Display all the elements of queue
4) Exit

Inputs:

Choose Insert (1) five times to input 10, 20, 30, 40, 50.

Enter your choice:


1
Insert the element in queue:
10
Enter your choice:
1
Insert the element in queue:
20
Enter your choice:
1
Insert the element in queue:
30
Enter your choice:
1
Insert the element in queue:
40
Enter your choice:
1
Insert the element in queue:
50

Queue after Insertions:

[10, 20, 30, 40, 50]

1. Display the queue (3).

Enter your choice:


3
Queue elements are: 10 20 30 40 50

2. Delete two elements (2) to remove 10 and 20.

Enter your choice:


2
Element deleted from queue is: 10
Enter your choice:
2
Element deleted from queue is: 20

Queue after Deletions:

[30, 40, 50]

Display the queue again (3).

Enter your choice:


3
Queue elements are: 30 40 50

3. Exit (4).

Enter your choice:


4
Exit

Final Output:

After taking the inputs 10, 20, 30, 40, 50 and performing operations as
described, the queue's operations produce:

Queue elements are: 10 20 30 40 50


Element deleted from queue is: 10
Element deleted from queue is: 20
Queue elements are: 30 40 50
Exit
2) Explain the insert and delete operation of the queue using linked list and write
the C++ function for the same

A queue is a linear data structure that follows the FIFO (First-In-First-Out)


principle, where elements are inserted at the rear and removed from the
front. Using a linked list, we can dynamically allocate memory for elements,
avoiding the fixed size limitation of an array.

Explanation of Insert and Delete Operations

1. Insert Operation (Enqueue):

• Purpose: Add a new element to the rear of the queue.


• Steps:
1. Create a new node using dynamic memory allocation.
2. Set the data of the new node.
3. If the queue is empty (front == nullptr), both front and
rear point to the new node.
4. Otherwise, link the new node to the current rear and update
rear to point to the new node.

2. Delete Operation (Dequeue):


CO3 L2 10M
• Purpose: Remove an element from the front of the queue.
• Steps:
1. If the queue is empty (front == nullptr), display "Queue
Underflow."
2. Otherwise, retrieve the data from the front node.
3. Move front to the next node and delete the old front node.
4. If the queue becomes empty after deletion, set rear =
nullptr.

C++ Implementation of Queue Using Linked List


#include <iostream>
using namespace std;

// Node structure
struct Node {
int data;
Node* next;
};

// Queue class using linked list


class Queue {
private:
Node* front; // Points to the front of the queue
Node* rear; // Points to the rear of the queue
public:
// Constructor
Queue() {
front = nullptr;
rear = nullptr;
}

// Insert operation (enqueue)


void Insert(int val) {
Node* newNode = new Node(); // Create a new node
newNode->data = val;
newNode->next = nullptr;

if (rear == nullptr) { // If the queue is empty


front = rear = newNode;
cout << "Inserted: " << val << endl;
} else { // Add the new node at the rear
rear->next = newNode;
rear = newNode;
cout << "Inserted: " << val << endl;
}
}

// Delete operation (dequeue)


void Delete() {
if (front == nullptr) { // Queue is empty
cout << "Queue Underflow" << endl;
return;
}

Node* temp = front; // Store the front node


cout << "Deleted: " << front->data << endl;
front = front->next; // Move front to the next node

if (front == nullptr) // If the queue becomes empty


rear = nullptr;

delete temp; // Free the memory of the old front node


}

// Display the queue


void Display() {
if (front == nullptr) {
cout << "Queue is empty" << endl;
return;
}

Node* temp = front;


cout << "Queue elements are: ";
while (temp != nullptr) {
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
};

int main() {
Queue q;
int choice, value;
cout << "1) Insert element to queue" << endl;
cout << "2) Delete element from queue" << endl;
cout << "3) Display all the elements of queue" << endl;
cout << "4) Exit" << endl;

do {
cout << "Enter your choice: ";
cin >> choice;

switch (choice) {
case 1:
cout << "Enter value to be inserted: ";
cin >> value;
q.Insert(value);
break;
case 2:
q.Delete();
break;
case 3:
q.Display();
break;
case 4:
cout << "Exiting..." << endl;
break;
default:
cout << "Invalid choice" << endl;
}
} while (choice != 4);

return 0;
}

Key Points of the Code:

1. Node Structure: Each node consists of data and a pointer next to


the next node.
2. Dynamic Allocation: Memory is allocated for each new node
dynamically using new.
3. Edge Cases:
o Handle queue underflow when front == nullptr.
o Reset rear to nullptr when the queue becomes empty after
deletion.
4. Queue Operations:
o Insert adds elements to the end of the list.
o Delete removes elements from the start of the list.
5. Display: Traverses the list from front to rear to print all elements.

Example Run:

Input:
1
10
1
20
1
30
3
2
3
4

Output:

Enter your choice: 1


Enter value to be inserted: 10
Inserted: 10
Enter your choice: 1
Enter value to be inserted: 20
Inserted: 20
Enter your choice: 1
Enter value to be inserted: 30
Inserted: 30
Enter your choice: 3
Queue elements are: 10 20 30
Enter your choice: 2
Deleted: 10
Enter your choice: 3
Queue elements are: 20 30
Enter your choice: 4
Exiting...

3) Sketch a Queue Q what is the value of front and rear after each of these
operations:
i) Insert item 50
ii) Insert item 10
iii) Insert item 30
iv) Delete an item
v) Delete an item.
With the size of Q is 5 has three elements 20, 40 and 60, where front = 0 and
rear = 2.

Let's simulate the queue operations step by step, keeping track of the queue
elements, front, and rear values. The queue's size is 5, and it initially CO3 L2 10M
contains the elements [20, 40, 60], with front = 0 and rear = 2.

Initial Queue State

• Queue: [20, 40, 60, _, _]


• Front: 0
• Rear: 2
Step-by-Step Operations

i) Insert item 50

1. Check if the queue is full: Since rear + 1 != front (circular


check), the queue has space.
2. Increment rear by 1 (from 2 to 3).
3. Insert 50 at rear = 3.

• Queue: [20, 40, 60, 50, _]


• Front: 0
• Rear: 3

ii) Insert item 10

1. Check if the queue is full: Since rear + 1 != front, the queue has
space.
2. Increment rear by 1 (from 3 to 4).
3. Insert 10 at rear = 4.

• Queue: [20, 40, 60, 50, 10]


• Front: 0
• Rear: 4

iii) Insert item 30

1. Check if the queue is full: Since rear + 1 == front, the queue is


full. No insertion is possible.
2. Display a message: "Queue Overflow."

• Queue (unchanged): [20, 40, 60, 50, 10]


• Front: 0
• Rear: 4

iv) Delete an item

1. Check if the queue is empty: Since front != rear + 1, the queue is


not empty.
2. Retrieve and remove the item at front = 0 (20).
3. Increment front by 1 (from 0 to 1).

• Queue: [_, 40, 60, 50, 10] (logically, 20 is removed)


• Front: 1
• Rear: 4

v) Delete an item

1. Check if the queue is empty: Since front != rear + 1, the queue is


not empty.
2. Retrieve and remove the item at front = 1 (40).
3. Increment front by 1 (from 1 to 2).

• Queue: [_, _, 60, 50, 10] (logically, 40 is removed)


• Front: 2
• Rear: 4

Final Queue State

• Queue: [_, _, 60, 50, 10]


• Front: 2
• Rear: 4

4) Demonstrate a C++ program to implement a queue using arrays and perform


its common operations.
#include <iostream>
using namespace std;

class Queue {
private:
CO3 L2 10M
int front, rear, size;
int *queue;
public:
Queue(int s) {
size = s;
front = rear = -1;
queue = new int[size];
}

// Enqueue operation
void enqueue(int value) {
if (rear == size - 1) {
cout << "Queue Overflow" << endl;
return;
}
if (front == -1) front = 0; // Initialize front during the first enqueue
rear++;
queue[rear] = value;
cout << value << " inserted into the queue." << endl;
}

// Dequeue operation
void dequeue() {
if (front == -1 || front > rear) {
cout << "Queue Underflow" << endl;
return;
}
cout << "Element " << queue[front] << " deleted from the queue." <<
endl;
front++;
}

// Display operation
void display() {
if (front == -1 || front > rear) {
cout << "Queue is empty" << endl;
return;
}
cout << "Queue elements: ";
for (int i = front; i <= rear; i++) {
cout << queue[i] << " ";
}
cout << endl;
}

~Queue() {
delete[] queue;
}
};

int main() {
int size, choice, value;
cout << "Enter the size of the queue: ";
cin >> size;

Queue q(size);

do {
cout << "\n1. Enqueue\n2. Dequeue\n3. Display\n4. Exit" << endl;
cout << "Enter your choice: ";
cin >> choice;

switch (choice) {
case 1:
cout << "Enter value to enqueue: ";
cin >> value;
q.enqueue(value);
break;
case 2:
q.dequeue();
break;
case 3:
q.display();
break;
case 4:
cout << "Exiting..." << endl;
break;
default:
cout << "Invalid choice!" << endl;
}
} while (choice != 4);

return 0;
}
OUTPUT:
Sample Output
Input:

Enter the size of the queue: 5

1. Enqueue
2. Dequeue
3. Display
4. Exit
Enter your choice: 1
Enter value to enqueue: 10
Enter your choice: 1
Enter value to enqueue: 20
Enter your choice: 1
Enter value to enqueue: 30
Enter your choice: 3
Enter your choice: 2
Enter your choice: 3
Enter your choice: 4
Output:
Enter the size of the queue: 5

1. Enqueue
2. Dequeue
3. Display
4. Exit
Enter your choice: 1
Enter value to enqueue: 10
10 inserted into the queue.

Enter your choice: 1


Enter value to enqueue: 20
20 inserted into the queue.

Enter your choice: 1


Enter value to enqueue: 30
30 inserted into the queue.

Enter your choice: 3


Queue elements: 10 20 30

Enter your choice: 2


Element 10 deleted from the queue.

Enter your choice: 3


Queue elements: 20 30

Enter your choice: 4


Exiting...
5) Sketch a Queue Q what is the value of front and rear after each of these
operations:
i) Delete a item
ii) Delete a item
iii) Insert item 7
iv) Delete an item. CO3 L2 10M
With the size of Q is 4 has three elements 4, 5, -9 and 66 where front = 0 and
rear = 3.

To analyze and sketch the state of the queue Q and determine the values of
front and rear after each operation, let’s walk through the scenario step by step:
Initial Queue State

Operation 1: Delete an item

Operation 2: Delete an item

Operation 3: Insert item 7

Operation 4: Delete an item


Summary of Operations
1. Delete an item:
o front = 1, rear = 3
2. Delete an item:
o front = 2, rear = 3
3. Insert item 7:
o front = 2, rear = 0
4. Delete an item:
o front = 3, rear = 0

6) Define standard template library of queue and write C++ program for the same
to represent all the operation of the queue.
Standard Template Library (STL) - Queue
The Standard Template Library (STL) in C++ provides a pre-defined queue
class under the <queue> header. It supports the FIFO (First-In-First-Out)
data structure. The operations provided by the STL queue include:
1. push(): Adds an element to the back of the queue.
2. pop(): Removes the front element of the queue.
3. front(): Accesses the front element.
4. back(): Accesses the last element.
5. empty(): Checks if the queue is empty.
6. size(): Returns the number of elements in the queue.

C++ Program Using STL Queue CO3 L2 10M


#include <iostream>
#include <queue> // Include the STL queue header
using namespace std;

int main() {
queue<int> q; // Create a queue of integers
int choice, value;

do {
cout << "\nQueue Operations using STL:" << endl;
cout << "1. Enqueue (push)" << endl;
cout << "2. Dequeue (pop)" << endl;
cout << "3. Display Front Element" << endl;
cout << "4. Display Rear Element" << endl;
cout << "5. Display Queue Size" << endl;
cout << "6. Check if Queue is Empty" << endl;
cout << "7. Exit" << endl;

cout << "Enter your choice: ";


cin >> choice;

switch (choice) {
case 1:
cout << "Enter the value to enqueue: ";
cin >> value;
q.push(value); // Enqueue operation
cout << value << " added to the queue." << endl;
break;

case 2:
if (!q.empty()) {
cout << "Dequeued element: " << q.front() << endl;
q.pop(); // Dequeue operation
} else {
cout << "Queue is empty. Cannot dequeue!" << endl;
}
break;

case 3:
if (!q.empty()) {
cout << "Front element: " << q.front() << endl;
} else {
cout << "Queue is empty." << endl;
}
break;

case 4:
if (!q.empty()) {
cout << "Rear element: " << q.back() << endl;
} else {
cout << "Queue is empty." << endl;
}
break;

case 5:
cout << "Queue size: " << q.size() << endl;
break;

case 6:
if (q.empty()) {
cout << "Queue is empty." << endl;
} else {
cout << "Queue is not empty." << endl;
}
break;

case 7:
cout << "Exiting..." << endl;
break;

default:
cout << "Invalid choice. Please try again." << endl;
}
} while (choice != 7);

return 0;
}

Explanation of the Program


1. Include <queue> Header:
o The <queue> header provides the queue container and
associated operations.
2. Queue Declaration:
o queue<int> q; declares a queue of integers.
3. Enqueue (push):
o q.push(value) adds an element to the back of the queue.
4. Dequeue (pop):
o q.pop() removes the element at the front of the queue.
o Note: pop() does not return the removed element. Use front() to
access it before popping.
5. Front and Rear Access:
o q.front() returns the front element.
o q.back() returns the rear element.
6. Queue Size:
o q.size() returns the number of elements in the queue.
7. Check if Empty:
o q.empty() returns true if the queue is empty; otherwise, false.

Sample Output
Input:
1. Enqueue (push)
2. Dequeue (pop)
3. Display Front Element
4. Display Rear Element
5. Display Queue Size
6. Check if Queue is Empty
7. Exit

Enter your choice: 1


Enter the value to enqueue: 10
Enter your choice: 1
Enter the value to enqueue: 20
Enter your choice: 3
Enter your choice: 4
Enter your choice: 2
Enter your choice: 5
Enter your choice: 7
Output:
Queue Operations using STL:
1. Enqueue (push)
2. Dequeue (pop)
3. Display Front Element
4. Display Rear Element
5. Display Queue Size
6. Check if Queue is Empty
7. Exit

Enter your choice: 1


Enter the value to enqueue: 10
10 added to the queue.

Enter your choice: 1


Enter the value to enqueue: 20
20 added to the queue.

Enter your choice: 3


Front element: 10

Enter your choice: 4


Rear element: 20

Enter your choice: 2


Dequeued element: 10

Enter your choice: 5


Queue size: 1

Enter your choice: 7


Exiting...
7) Explain Priority queue and write C++ standard template library code for the
same.
Priority Queue
A priority queue is a specialized data structure where elements are dequeued
based on their priority rather than their insertion order.
1. Types of Priority Queues:
o Max Priority Queue: Highest value has the highest priority.
o Min Priority Queue: Lowest value has the highest priority.
2. Operations:
o push(): Insert an element.
o pop(): Remove the highest-priority element.
o top(): Access the highest-priority element.
o empty(): Check if the queue is empty.
o size(): Get the number of elements.

C++ Program for Priority Queue Using STL


#include <iostream>
#include <queue>
using namespace std;

int main() {
priority_queue<int> maxPQ; // Max Priority Queue
priority_queue<int, vector<int>, greater<int>> minPQ; // Min Priority
CO3 L2 10M
Queue

maxPQ.push(10); maxPQ.push(20); maxPQ.push(5);


minPQ.push(10); minPQ.push(20); minPQ.push(5);

cout << "Max Priority Queue: ";


while (!maxPQ.empty()) { cout << maxPQ.top() << " "; maxPQ.pop(); }
cout << "\nMin Priority Queue: ";
while (!minPQ.empty()) { cout << minPQ.top() << " "; minPQ.pop(); }

return 0;
}

Sample Output
Max Priority Queue: 20 10 5
Min Priority Queue: 5 10 20

Applications
• Task scheduling, graph algorithms (Dijkstra’s, Prim’s), real-time data
processing.
Complexity
• O(log n) for insertion and deletion.
8) Construct a C++ program that performs linear search using an array of integer
value and mention the time complexity of the linear search in best case, worst
case and average case.
Linear Search in C++
A linear search is a simple search algorithm that checks each element in a list
sequentially until the target element is found or the list ends.
C++ Program for Linear Search
#include <iostream>
using namespace std;

int linearSearch(int arr[], int size, int target) {


for (int i = 0; i < size; i++) {
if (arr[i] == target) {
return i; // Element found, return index
}
}
return -1; // Element not found
}

int main() {
int arr[] = {34, 7, 23, 32, 5, 62};
int size = sizeof(arr) / sizeof(arr[0]);
int target;
CO3 L3 10M
cout << "Enter the element to search: ";
cin >> target;

int result = linearSearch(arr, size, target);

if (result != -1) {
cout << "Element " << target << " found at index " << result << endl;
} else {
cout << "Element " << target << " not found in the array." << endl;
}

return 0;
}
Explanation of the Program
1. Input:
o An array of integers arr[] is defined with values {34, 7, 23, 32,
5, 62}.
o The program takes an integer target as input, which is the value
to be searched in the array.
2. linearSearch() Function:
o The function iterates through the array to check if the element
matches the target.
o If the element is found, the index is returned.
o If the element is not found after checking all elements, -1 is
returned.
3. Output:
o If the element is found, the program prints the index where the
element is located.
o If the element is not found, it prints that the element is not in
the array.
Time Complexity of Linear Search
1. Best Case: O(1)
o The best case occurs when the target element is the first element
in the array. The search is completed in one step.
2. Worst Case: O(n)
o The worst case occurs when the target element is not present in
the array or is the last element. The entire array must be
searched, so it takes n comparisons.
3. Average Case: O(n)
o On average, the target element will be located in the middle of
the array. Therefore, half of the elements will be checked, but
the time complexity remains O(n) since constant factors are
ignored.
Sample Input and Output
Input:
Enter the element to search: 32
Output:
Element 32 found at index 3
Summary of Time Complexity
• Best Case: O(1)
• Worst Case: O(n)
• Average Case: O(n)

9) Write a C++ program that performs binary search using an array of real values.
Binary Search in C++
Binary Search is an efficient search algorithm that works on sorted arrays.
It repeatedly divides the search interval in half. If the value of the target is less
than the item in the middle of the interval, the search continues in the lower
half, otherwise, it continues in the upper half.
C++ Program for Binary Search
#include <iostream> CO3 L2 10M
#include <vector>
#include <algorithm>
using namespace std;

int binarySearch(const vector<double>& arr, int size, double target) {


int low = 0;
int high = size - 1;
while (low <= high) {
int mid = low + (high - low) / 2;

// Check if the target is at mid


if (arr[mid] == target) {
return mid; // Element found at index mid
}

// If target is smaller, search in the left half


if (arr[mid] > target) {
high = mid - 1;
}
// If target is larger, search in the right half
else {
low = mid + 1;
}
}
return -1; // Element not found
}

int main() {
// Array of real numbers (sorted)
vector<double> arr = {1.5, 3.2, 5.6, 7.3, 8.0, 9.9, 12.4, 14.5, 16.2};

double target;
cout << "Enter the element to search: ";
cin >> target;

// Get the size of the array


int size = arr.size();

// Perform binary search


int result = binarySearch(arr, size, target);

// Output the result


if (result != -1) {
cout << "Element " << target << " found at index " << result << endl;
} else {
cout << "Element " << target << " not found in the array." << endl;
}

return 0;
}
Explanation of the Program
1. Input:
o The program defines a sorted array of real values (arr[]) with
values {1.5, 3.2, 5.6, 7.3, 8.0, 9.9, 12.4, 14.5, 16.2}.
o The user is prompted to enter a target value (target), which is
the number to search for in the array.
2. binarySearch() Function:
o The function takes a sorted array (arr[]), the size of the array
(size), and the target value (target).
o It initializes two indices: low (beginning of the array) and high
(end of the array).
o The algorithm keeps dividing the array in half and compares
the middle element (mid) with the target:
▪ If arr[mid] equals the target, the index mid is returned.
▪ If the target is smaller, the search continues in the left
half (high = mid - 1).
▪ If the target is larger, the search continues in the right
half (low = mid + 1).
o If the target is not found, it returns -1.
3. Output:
o If the element is found, the program prints the index where the
element is located.
o If the element is not found, it prints a message stating that the
element is not in the array.
Time Complexity of Binary Search
• Best Case: O(1) — The target is found at the middle element.
• Worst Case: O(log n) — The search space is halved at each step, so
the number of comparisons grows logarithmically with the size of the
array.
• Average Case: O(log n) — Like the worst case, binary search works
by halving the search space, regardless of where the element is located.
Sample Input and Output
Input:
Enter the element to search: 7.3
Output:
Element 7.3 found at index 3
Input:
Enter the element to search: 10.5
Output:
Element 10.5 not found in the array.
Summary
• Binary Search is highly efficient for searching in sorted arrays, with a
time complexity of O(log n) in both the worst and average cases.
• It is much faster than linear search for large datasets, especially when
the data is already sorted.

10) What is hashing? And explain the working and components of hashing with
CO3 L2 5M
an example.
Hashing
Hashing is a technique used to uniquely identify and store data in a table using
a hash function, which maps keys to hash values (indices). It allows for
efficient data retrieval.
Components of Hashing
1. Hash Function: A function that converts a key into an integer (hash
value). Example: hashValue = key % tableSize.
2. Hash Table: A data structure that stores elements at indices computed
by the hash function.
3. Collision Handling:
o Chaining: Store elements in a linked list at the same index.
o Open Addressing: Find another empty spot (e.g., linear
probing).
4. Buckets: Containers in the table where data is stored.
Working of Hashing
1. Insertion: The key is hashed, and the data is inserted at the
corresponding index in the hash table. If a collision occurs, it’s handled
by chaining or open addressing.
2. Search: The key is hashed, and the corresponding index is checked for
the presence of the element.
3. Deletion: The key is hashed, and the element is removed from the
corresponding index.
Example
For data elements 23, 45, 12, 17, 34 and a table size of 10, using hashValue =
key % 10, the elements are inserted at the following indices:
• 23 → index 3
• 45 → index 5
• 12 → index 2
• 17 → index 7
• 34 → index 4
If there’s a collision (e.g., inserting 15, which hashes to 5), chaining is used to
store 15 in the linked list at index 5.
C++ Code Example
#include <iostream>
#include <list>
using namespace std;

class HashTable {
int tableSize;
list<int>* table;

public:
HashTable(int size) {
tableSize = size;
table = new list<int>[tableSize];
}
int hashFunction(int key) {
return key % tableSize;
}

void insert(int key) {


int index = hashFunction(key);
table[index].push_back(key);
}

bool search(int key) {


int index = hashFunction(key);
for (auto it : table[index]) {
if (it == key) return true;
}
return false;
}

void remove(int key) {


int index = hashFunction(key);
table[index].remove(key);
}

void display() {
for (int i = 0; i < tableSize; i++) {
cout << "Index " << i << ": ";
for (auto it : table[i]) {
cout << it << " -> ";
}
cout << "NULL" << endl;
}
}
};

int main() {
HashTable ht(10);
ht.insert(23);
ht.insert(45);
ht.insert(12);
ht.insert(17);
ht.insert(34);
ht.display();

if (ht.search(17)) cout << "17 found!" << endl;


else cout << "17 not found!" << endl;
ht.remove(12);
ht.display();

return 0;
}
Time Complexity
• Average Case: O(1) for insertion, search, and deletion.
• Worst Case: O(n) when collisions cause long linked lists.
Hashing allows efficient data storage and retrieval, but collision handling is
essential for maintaining performance.

11) Explain the linear probing technique to overcome the collision in hashing and
write the C++ program for the same.
Linear Probing in Hashing
Linear Probing is a collision resolution technique used in hash tables. When
two or more keys hash to the same index (collision), linear probing searches
for the next available empty slot in the array to store the key. This technique
works by checking subsequent array locations in a linear fashion until an open
slot is found.
How Linear Probing Works
1. Insertion: When inserting a key, calculate the hash value. If the
position is occupied, check the next position, and repeat this process
until an empty slot is found.
2. Search: After calculating the hash, if the slot is occupied but the key is
not found, check the next slot, and continue searching until either the
key is found or an empty slot is reached.
3. Deletion: When deleting a key, remove it and rehash the subsequent
elements that were stored using linear probing.
Advantages of Linear Probing CO3 L2 10M
• Simple to implement.
• Efficient when the table has fewer collisions.
Disadvantages of Linear Probing
• Clustering: If many elements hash to the same location, it can lead to
"primary clustering," where groups of consecutive occupied slots form,
reducing efficiency.
• Performance degrades if the table is too full.
C++ Program Implementing Linear Probing
#include <iostream>
using namespace std;

class HashTable {
int* table;
int tableSize;
int currentSize;

public:
// Constructor
HashTable(int size) {
tableSize = size;
table = new int[tableSize];
currentSize = 0;

// Initialize the table with -1 (empty slots)


for (int i = 0; i < tableSize; i++) {
table[i] = -1;
}
}

// Hash function to calculate the hash value


int hashFunction(int key) {
return key % tableSize;
}

// Insert a key into the hash table using linear probing


void insert(int key) {
if (currentSize == tableSize) {
cout << "Hash Table is full!" << endl;
return;
}

int index = hashFunction(key);

// Linear probing: Find the next available slot


while (table[index] != -1) {
index = (index + 1) % tableSize;
}

table[index] = key;
currentSize++;
}

// Search for a key in the hash table using linear probing


bool search(int key) {
int index = hashFunction(key);

// Linear probing: Search for the key


while (table[index] != -1) {
if (table[index] == key) {
return true;
}
index = (index + 1) % tableSize;
}
return false;
}

// Delete a key from the hash table using linear probing


void remove(int key) {
int index = hashFunction(key);

// Linear probing: Search and remove the key


while (table[index] != -1) {
if (table[index] == key) {
table[index] = -1;
currentSize--;
cout << "Key " << key << " removed." << endl;
return;
}
index = (index + 1) % tableSize;
}

cout << "Key " << key << " not found." << endl;
}

// Display the contents of the hash table


void display() {
for (int i = 0; i < tableSize; i++) {
if (table[i] != -1) {
cout << "Index " << i << ": " << table[i] << endl;
} else {
cout << "Index " << i << ": Empty" << endl;
}
}
}
};

int main() {
HashTable ht(10);

// Inserting elements
ht.insert(15);
ht.insert(25);
ht.insert(35);
ht.insert(45);

ht.display();

// Searching for an element


if (ht.search(25)) {
cout << "25 found!" << endl;
} else {
cout << "25 not found!" << endl;
}

// Removing an element
ht.remove(25);
ht.display();

return 0;
}
Explanation of the Program
1. Hash Table Initialization: The table is initialized with a fixed size (10
in this case), and each slot is initially set to -1 to indicate an empty slot.
2. Hash Function: The hash function key % tableSize is used to compute
the index for storing a key in the table.
3. Insertion: The insert() function calculates the hash index for a key. If
the slot is already occupied, it moves to the next slot using linear
probing until an empty slot is found.
4. Search: The search() function calculates the hash index and searches
for the key using linear probing. If the key is found, it returns true;
otherwise, it returns false.
5. Deletion: The remove() function deletes the key if found by linear
probing. After deletion, it adjusts the table by marking the slot as empty
(-1).
6. Display: The display() function prints all the non-empty elements in
the hash table.
Example Output
Index 0: Empty
Index 1: Empty
Index 2: Empty
Index 3: 15
Index 4: Empty
Index 5: 25
Index 6: Empty
Index 7: 35
Index 8: 45
Index 9: Empty
25 found!
Key 25 removed.
Index 0: Empty
Index 1: Empty
Index 2: Empty
Index 3: 15
Index 4: Empty
Index 5: Empty
Index 6: Empty
Index 7: 35
Index 8: 45
Index 9: Empty
Time Complexity
• Insertion: In the best case, the time complexity is O(1) if the hash
value maps to an empty slot. In the worst case, the time complexity
can become O(n) if many slots are occupied, and linear probing
searches the entire table.
• Search: Similar to insertion, in the best case, it takes O(1) time. In the
worst case, it can take O(n) time if the table is full and all elements
need to be checked.
• Deletion: The deletion process also involves linear probing, so the time
complexity is O(n) in the worst case if the element is found near the
end of the table.

Linear probing is an effective and simple collision resolution technique.


However, it may lead to primary clustering, where groups of consecutive
occupied slots degrade performance, especially as the table fills up. This can
be mitigated by using better probing techniques like quadratic probing or
double hashing.

12) Explain the quadratic probing to overcome the collision in hashing.


Quadratic Probing in Hashing
Quadratic Probing is a collision resolution technique used in open addressing
hashing. When a collision occurs (i.e., two keys hash to the same index),
quadratic probing searches for the next available slot using a quadratic function
instead of a linear one. This reduces the primary clustering problem found in
linear probing.
How Quadratic Probing Works
1. Insertion: When inserting a key, if the hash index is already occupied,
quadratic probing checks the next index using the formula:
New index=(h+i2)mod table size\text{New index} = (h + i^2) \mod
\text{table size}
where: CO3 L2 10M
o hh is the original hash index.
o ii is the number of attempts or probes (starting from 1, 2, 3, ...).
o The process continues until an empty slot is found.
2. Search: Similar to insertion, if the key does not exist at the calculated
index, quadratic probing checks subsequent positions by incrementing
ii and applying the quadratic formula.
3. Deletion: The deletion is handled similarly to linear probing, but the
next slots are checked using the quadratic formula for possible
subsequent probes.
Advantages of Quadratic Probing
• Reduces primary clustering compared to linear probing by spreading
out the probing sequence.
• Helps in handling collisions more effectively when the hash table is
sparsely populated.
Disadvantages of Quadratic Probing
• Secondary clustering: Although quadratic probing reduces primary
clustering, it may still cause secondary clustering (where keys hashing
to the same index follow the same probing sequence).
• The table size must be chosen carefully, usually a prime number, to
ensure that quadratic probing can visit all slots.
Example Formula
For an original hash hh and a key kk, the probing sequence is:
• Index=(h+12)mod table size\text{Index} = (h + 1^2) \mod \text{table
size}
• Index=(h+22)mod table size\text{Index} = (h + 2^2) \mod \text{table
size}
• Index=(h+32)mod table size\text{Index} = (h + 3^2) \mod \text{table
size}

Quadratic probing is a useful technique for resolving collisions in hashing,


providing better performance than linear probing by avoiding large clusters of
occupied slots. However, choosing the right table size and probing function is
essential to achieve optimal results.

13) Apply selection sort technique for the data: 74, 39, 35,32,97,84. Demonstrate
a C++ program for selection sort.
Selection Sort Explanation
Selection Sort is a simple comparison-based sorting algorithm. The algorithm
repeatedly selects the smallest (or largest, depending on the sorting order)
element from the unsorted portion of the list and swaps it with the first unsorted
element. The process continues until the entire list is sorted.
Steps of Selection Sort:
1. Start from the first element of the array.
2. Find the minimum (or maximum) element in the unsorted part of the
array.
3. Swap the minimum element with the element at the current position.
4. Move the boundary of the sorted part of the array one element forward.
5. Repeat the process until the entire array is sorted.
CO3 L2 10M
Selection Sort C++ Program
#include <iostream>
using namespace std;

void selectionSort(int arr[], int n) {


for (int i = 0; i < n - 1; i++) {
// Find the minimum element in the unsorted portion of the array
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// Swap the found minimum element with the element at index i
if (minIndex != i) {
swap(arr[i], arr[minIndex]);
}
}
}

void displayArray(int arr[], int n) {


for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

int main() {
int arr[] = {74, 39, 35, 32, 97, 84};
int n = sizeof(arr) / sizeof(arr[0]);

cout << "Array before sorting: ";


displayArray(arr, n);

selectionSort(arr, n);

cout << "Array after sorting: ";


displayArray(arr, n);

return 0;
}
Explanation of the Code:
1. selectionSort function: This function sorts the array using the
selection sort technique. It iterates through each element, finds the
smallest element in the unsorted portion, and swaps it with the first
unsorted element.
2. displayArray function: This function prints the elements of the array.
3. main function: Initializes the array and calls both selectionSort and
displayArray to demonstrate the sorting process.
Output:
Array before sorting: 74 39 35 32 97 84
Array after sorting: 32 35 39 74 84 97

The time complexity of selection sort is O(n^2) in all cases because it always
performs two nested loops.

14) Define shell sort and also with C++ function to sort the array of integers using
shell sort.
Shell Sort:
CO3 L2 10M
Shell Sort is an algorithm that generalizes the insertion sort to allow the
exchange of items that are far apart. The idea is to arrange the elements of the
array in such a way that the elements that are far apart are compared and sorted
first. This reduces the number of inversions and brings the array closer to being
sorted.
The main idea behind Shell Sort is to use a gap sequence. The array is divided
into subarrays based on a gap, and insertion sort is applied to each of these
subarrays. Initially, the gap is large, and it reduces over time, eventually
performing an insertion sort on the entire array when the gap becomes 1.
Steps in Shell Sort:
1. Start by choosing an initial gap size. Typically, the gap starts as half
the size of the array.
2. For each gap, perform an insertion sort on the elements that are gap
distance apart.
3. Gradually reduce the gap until it becomes 1, at which point the array
will be fully sorted using a regular insertion sort.
C++ Program for Shell Sort:
#include <iostream>
using namespace std;

// Function to perform Shell Sort


void shellSort(int arr[], int n) {
// Start with a large gap, then reduce it
for (int gap = n / 2; gap > 0; gap /= 2) {
// Perform a gapped insertion sort for this gap size
for (int i = gap; i < n; i++) {
int temp = arr[i];
int j = i;

// Shift earlier gap-sorted elements to make space for the current


element
while (j >= gap && arr[j - gap] > temp) {
arr[j] = arr[j - gap];
j -= gap;
}
arr[j] = temp;
}
}
}

// Function to print the array


void printArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " ";
}
cout << endl;
}

int main() {
int arr[] = {74, 39, 35, 32, 97, 84}; // Example array
int n = sizeof(arr) / sizeof(arr[0]); // Get the size of the array

cout << "Original Array: ";


printArray(arr, n);

// Perform Shell Sort


shellSort(arr, n);

cout << "Sorted Array: ";


printArray(arr, n);

return 0;
}
Explanation of the Code:
1. shellSort Function:
o The function begins with a large gap size (half the size of the
array) and iteratively reduces the gap by halving it each time.
o For each gap size, we perform a gapped insertion sort.
Elements are compared and swapped with a gap of gap
positions, which gradually moves the elements closer to their
final position.
2. printArray Function:
o This function simply prints the elements of the array.
3. Main Function:
o Initializes an example array of integers.
o Calls the shellSort function to sort the array.
o Prints the array before and after sorting.
Example Output:
Original Array: 74 39 35 32 97 84
Sorted Array: 32 35 39 74 84 97

Shell Sort is faster than basic insertion sort due to the reduced number of
comparisons and swaps, especially when the gap is large at the beginning.
However, its performance highly depends on the gap sequence chosen.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy