DSA Lab Manual
DSA Lab Manual
Data Structures
COMP2117
Submitted By
Name: _______________________________________________________
Roll#: _______________________________________________________
F E AT U R E S
To ensure a successful experience for instructors and students alike, this lab manual includes the
following features:
Lab Objectives—Every lab has a brief description and list of learning objectives.
Materials required—Every lab includes information on software you will need to complete
the lab.
Completion Times—Every lab has an estimated completion time so that you can plan your
activities more accurately.
Review Questions—Some labs include review questions to help reinforce concepts presented
in the lab.
Some lab assignments require written answers to complete an exercise, while others are
programming assignments that require you to work with a C++ compiler.
Check with your instructor for instructions on completing the written assignments. For
example, you can print pages directly from the appropriate editor, and then write directly on
the page.
To complete the programming assignments, use the compiler that your instructor recommends
or requires.
Print all the documentation assigned, including program code, program prompts, input, and
output displayed on the screen, input files, and output files.
You can submit your written answers and the printed documentation with a lab cover sheet
for grading.
If your instructor requires an electronic copy of your work, e-mail the completed assignment
to your instructor or include a removable disk with your work.
Your instructor will tell you what is needed, but be sure to submit the .cpp.
To provide program documentation, compile and run your program, copy the prompts, input,
and output (if appropriate), and paste them as a block comment at the end of your program.
Use the Copy and Paste features of your C++ program development kit to do so. After you
paste the comment in the program, either print the program file from your text editor or
submit the program file to your instructor electronically.
Array:
An array in Data Structures and Algorithms (DSA) is a data structure that
stores a collection of elements (usually of the same data type) in contiguous memory
locations. Arrays are fundamental and are used in numerous algorithms. Below is a
summary of key algorithms involving arrays and their use cases.
Basic Array Operations
a. Traversal
Code:
#include <iostream>
int main() {
int n;
cin >> n;
int arr[n];
cout << "Enter " << n << " elements:" << endl;
return 0;}
Output:
Insertion
Code:
#include <iostream>
int main() {
cin >> n;
arr[pos] = value;
n++;
return 0;}
Output:
Deletion
Code:
#include <iostream>
using namespace std;
int main() {
int n, pos;
cout << "Enter the size of the array: ";
cin >> n;
int arr[n];
cout << "Enter " << n << " elements: ";
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
cout << "Enter the position to delete the element: ";
cin >> pos;
for (int i = pos; i < n - 1; i++) {
arr[i] = arr[i + 1];
}
n--;
cout << "Array after deletion: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " "; }
cout << endl;
return 0;
}
Output:
Searching
1. Worst-case time complexity: O(n)O(n)O(n), where nnn is the number of elements in the array.
2. Simple implementation, but not efficient for large datasets compared to more advanced search
algorithms like binary search.
Code:
#include <iostream>
int main() {
cin >> n;
int arr[n];
if (arr[i] == key) {
flag = 1;
break; } }
if (!flag) {
return 0;
Output:
Binary Search:
Code:
#include <iostream>
if (arr[mid] == key) {
return mid;
low = mid + 1;
int main() {
int n, key;
cin >> n;
int arr[n];
cout << "Enter " << n << " sorted elements: ";
if (result != -1) {
cout << "Element found at position " << result << endl;
} else {
} return 0;
Output:
Sorting:
Bubble Sort
Description: Repeatedly swap adjacent elements if they are in the wrong order.
Time Complexity: O(n2)O(n^2)O(n2)
Code:
#include <iostream>
int main() {
int n;
cin >> n;
int arr[n];
return 0;}
Output:
Insertion Sort:
Time Complexity:
Code:
#include <iostream>
int main() {
int n;
cin >> n;
int arr[n];
int j = i - 1;
arr[j + 1] = arr[j];
j = j - 1;
arr[j + 1] = key; }
cout << "Sorted array: ";
return 0;
Output:
Selection Sort:
Time Complexity:
Best Case: O(n2)O(n^2)O(n2) (Selection sort doesn't change based on the input).
Average and Worst Case: O(n2)O(n^2)O(n2).
Code:
#include <iostream>
int main() {
int n;
cin >> n;
int arr[n];
int minIndex = i;
minIndex = j;
if (minIndex != i) {
swap(arr[i], arr[minIndex]); }}
return 0;
Output:
Quick Sort
Description: Divide and conquer algorithm that selects a pivot and partitions the array around it.
Time Complexity: O(nlogn)O(n \log n)O(nlogn) (average), O(n2)O(n^2)O(n2) (worst).
Code:
#include <iostream>
int i = low - 1;
i++;
swap(arr[i], arr[j]);
return i + 1;
quickSort(arr, pi + 1, high);
int main() {
int n;
cin >> n;
int arr[n];
quickSort(arr, 0, n - 1);
return 0;
Output:
Merge Sort
Description: Recursively divide the array into halves, sort, and merge them.
Time Complexity: O(nlogn)O(n \log n)O(nlogn)
Code:
#include <iostream>
int i = 0, j = 0, k = left;
arr[k] = L[i];
i++;
} else {
arr[k] = R[j];
j++;
k++;
arr[k] = L[i];
i++;
k++;
}
arr[k] = R[j];
j++;
k++;
int main() {
int n;
cin >> n;
int arr[n];
mergeSort(arr, 0, n - 1);
return 0;
Output:
A stack is a linear data structure that follows the Last In First Out (LIFO) principle. This means the
last element added to the stack is the first one to be removed. A stack supports two main operations:
Peek (or Top): View the top element without removing it.
isEmpty: Check if the stack is empty.
Size: Get the number of elements in the stack.
Push (Insertion)
Code:
#include <iostream>
class Stack {
int *arr;
int top;
int capacity;
public:
Stack(int size) {
capacity = size;
top = -1;
if (top == capacity - 1) {
return; }
arr[++top] = value;
void display() {
if (top == -1) {
cout << "Stack is empty" << endl;
return;
~Stack() {
delete[] arr; }
};
int main() {
int n;
cin >> n;
Stack stack(n);
int value;
cout << "Enter values to push into the stack (enter -1 to stop):" << endl;
while (true) {
stack.push(value);
stack.display();
return 0;
Output:
Peek/Top
Description: Retrieve the element from the top of the stack without removing it.
Time Complexity: O(1)O(1)O(1)
Code:
#include <iostream>
#include <stack>
class MyStack {
private:
std::stack<int> stack;
public:
stack.push(item);
void pop() {
if (!isEmpty()) {
stack.pop();
} else {
int peek() {
if (!isEmpty()) {
return stack.top();
} else {
return -1;
bool isEmpty() {
return stack.empty();
int size() {
return stack.size();
};
int main() {
MyStack stack;
stack.push(10);
stack.push(20);
stack.push(30);
std::cout << "Peek after pop: " << stack.peek() << std::endl;
return 0;
Output:
isEmpty
Code:
#include <iostream>
class Stack {
int *arr;
int top;
int capacity;
public:
Stack(int size) {
capacity = size;
top = -1;
}
bool isEmpty() {
if (top == capacity - 1) {
return;
arr[++top] = value;
void display() {
if (top == -1) {
return;
~Stack() {
delete[] arr;
};
int main() {
int n;
cin >> n;
Stack stack(n);
cout << "Is the stack empty? " << (stack.isEmpty() ? "Yes" : "No") << endl;
stack.push(10);
stack.push(20);
stack.push(30);
cout << "Is the stack empty? " << (stack.isEmpty() ? "Yes" : "No") << endl;
stack.display();
return 0;
Output:
Queue
A queue is a data structure that operates on the First In, First Out (FIFO) principle, meaning the
first element added to the queue is the first one to be removed. Queues are widely used in computer
science for tasks like scheduling, buffering, and managing resources in order.
Time Complexity:
Basic Operations:
Code:
#include <iostream>
#include <vector>
class Queue {
vector<int> queue;
int capacity;
public:
queue.push_back(item); }
int dequeue() {
if (!isEmpty()) {
queue.erase(queue.begin());
return front; }
return -1;
} int peek() {
if (!isEmpty())
return queue.front();
return -1;
bool isEmpty() {
return queue.empty(); }
bool isFull() {
int main() {
Queue q(5);
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);
cout << "Front element after dequeue: " << q.peek() << endl;
q.enqueue(40);
q.enqueue(50);
q.enqueue(60);
cout << "Is queue full: " << (q.isFull() ? "Yes" : "No") << endl;
while (!q.isEmpty())
cout << "Is queue empty: " << (q.isEmpty() ? "Yes" : "No") << endl;
return 0;
OUTPUT:
Circular Queue
A circular queue is a variation of a linear queue where the last position is connected back to the first
position, forming a circle. This design allows the queue to efficiently use memory by reusing spaces
that become available after dequeue operations.
1. Circular Connection:
o The rear of the queue wraps around to the front when it reaches the end of the allocated
space, enabling continuous use of the array.
3. Indexing:
o The positions are managed using modular arithmetic:
rear = (rear + 1) % size (to move forward for enqueue).
front = (front + 1) % size (to move forward for dequeue).
Basic Operations
class Queue {
int* queue;
public:
~Queue() {
delete[] queue; }
if (!isFull()) {
queue[rear] = item; }}
int dequeue() {
if (!isEmpty()) {
return item; }
return -1;}
int peek() {
if (!isEmpty())
return queue[front];
return -1; }
bool isEmpty() {
}};
int main() {
Queue q(5);
q.enqueue(10);
q.enqueue(20);
q.enqueue(30);
q.enqueue(40);
cout << "Front element after dequeue: " << q.peek() << endl;
q.enqueue(50);
q.enqueue(60);
cout << "Is queue full: " << (q.isFull() ? "Yes" : "No") << endl;
while (!q.isEmpty())
cout << "Is queue empty: " << (q.isEmpty() ? "Yes" : "No") << endl;
return 0;
Output:
Simple Linked List
A simple linked list is a linear data structure where elements, called nodes, are connected using
pointers. Each node contains two parts:
The list starts with a special node called the head, and the last node points to NULL (indicating the
end of the list).
Basic Operations
At the End
Code
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int val) {
data = val;
class LinkedList {
Node* head;
public:
LinkedList() {
head = nullptr;
if (head == nullptr) {
head = newNode;
} else {
temp = temp->next;
temp->next = newNode; }
void traverse() {
temp = temp->next; }
int main() {
LinkedList list;
list.insertAtEnd(10);
list.insertAtEnd(20);
list.insertAtEnd(30);
list.traverse();
list.insertAtEnd(40);
list.insertAtEnd(50);
list.traverse();
return 0;
}
OUTPUT