0% found this document useful (0 votes)
21 views35 pages

DSA Lab Manual

The lab manual for Data Structures (COMP2117) outlines a series of experiments aimed at familiarizing students with programming concepts and coding techniques in C++/Java. It includes detailed lab objectives, required materials, completion times, and step-by-step instructions for various data structure implementations such as arrays, linked lists, and sorting algorithms. The manual is designed to enhance technical proficiency and includes review questions and critical thinking exercises to reinforce learning.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
0% found this document useful (0 votes)
21 views35 pages

DSA Lab Manual

The lab manual for Data Structures (COMP2117) outlines a series of experiments aimed at familiarizing students with programming concepts and coding techniques in C++/Java. It includes detailed lab objectives, required materials, completion times, and step-by-step instructions for various data structure implementations such as arrays, linked lists, and sorting algorithms. The manual is designed to enhance technical proficiency and includes review questions and critical thinking exercises to reinforce learning.
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1/ 35

Lab Manual

Data Structures
COMP2117

Course Name Data Structure


Course Code COMP2117
Credit Hours 4(3+3)
Program BSIT/ BSCS
Semester III

Submitted By
Name: _______________________________________________________

Roll#: _______________________________________________________

Department of Information Sciences,

University of Education, Lahore.


Data Structures & Analysis of Algorithms
List of Experiments
Lab No. Lab Title Page

Lab # 1 Implementing Arrays in C++/ Java

Lab # 2 Implementing Pointers in C++

Lab # 3 Array Bounds (Overflow/ Underflow) Checking

Lab # 4 Array-based Implementation of List ADT

Lab # 5 Array-based Implementation of Queue ADT

Lab # 6 Array-based Implementation of Drifting Queue

Lab # 7 Array-based Implementation of Circular Queue

Lab # 8 Array-based Implementation of Stack ADT

Lab # 9 Array-based Implementation of Two-way Stack ADT

Lab # 10 Searching a value in a List

Lab # 11 Searching and Replacing a value in a List

Lab # 12 Implementation of Linked List

Lab # 13 Linked List Based Implementation of List ADT

Lab # 14 Linked List Based Implementation of Queue ADT

Lab # 15 Linked List Based Implementation of Stack ADT


Introduction
The objective of this lab manual is to give students step-by-step examples to become familiar with
programming concepts, design, and coding.

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.

 Activity Sections—Labs are presented in manageable sections; where appropriate, additional


Activity Background information is provided to illustrate the importance of a particular
activity.

 Step-by-Step Instructions—Every lab provides steps to enhance technical proficiency; some


labs include Critical Thinking exercises to challenge students.

 Review Questions—Some labs include review questions to help reinforce concepts presented
in the lab.

 SOFTWA R E REQUIREMENTS —Computer running Windows 8 or higher, Recommended


compiler is DevC++ v5 or higher, Code Blocks IDE, Visual Studio Code, or similar.

COMPLETING THE LAB ASSIGNMENTS

 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.

A typical C++ environment


Lab-1: Implementing Arrays in C++/ Java
Description of the Experiment:
In this experiment, we will see how an array is implementing in programming languages, for
example, C++ or Java.
Inputs:
User will provide values to be stored in the array.
Output:
Array contents will be displayed.
Special Conditions/ Errors:
NA
Source Code:
#include<iostream>
using namespace std;
int main(){
int A[5];
for(int i=0; i < 5; i++)
cin>>A[i];
for(int j=0; j<5; j++)
cout<<A[j]<<" ";
return 0;
}
Screenshot of Output:

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

 Description: Visit each element in the array.


 Time Complexity: O(n)O(n)O(n)

Code:

#include <iostream>

using namespace std;

int main() {

int n;

cout << "Enter the size of the array: ";

cin >> n;

int arr[n];

cout << "Enter " << n << " elements:" << endl;

for (int i = 0; i < n; i++) {

cin >> arr[i];

cout << "The elements of the array are: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " "; }

cout << endl;

return 0;}

Output:
Insertion

 Description: Insert an element at a specific position.


 Time Complexity:
o O(1)O(1)O(1) for appending.
o O(n)O(n)O(n) for insertion at a specific position (due to shifting).

Code:
#include <iostream>

using namespace std;

int main() {

int n, pos, value;

cout << "Enter the size of the array: ";

cin >> n;

int arr[n + 1];

cout << "Enter " << n << " elements: ";

for (int i = 0; i < n; i++) {

cin >> arr[i];

cout << "Enter the position to insert the element: ";

cin >> pos;

cout << "Enter the value to insert: ";

cin >> value;

for (int i = n; i > pos; i--) {

arr[i] = arr[i - 1];

arr[pos] = value;

n++;

cout << "Array after insertion: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " "; }

cout << endl;

return 0;}
Output:

Deletion

 Description: Remove an element at a specific position.


 Time Complexity: O(n)O(n)O(n) (due to shifting).

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

 Linear Search: O(n)O(n)O(n)


 Binary Search: O(log⁡n)O(\log n)O(logn) (array must be sorted).

Key Characteristics of Linear Search:

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>

using namespace std;

int main() {

int n, key, flag = 0;

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 element to search: ";

cin >> key;


for (int i = 0; i < n; i++) {

if (arr[i] == key) {

cout << "Element found at position " << i << endl;

flag = 1;

break; } }

if (!flag) {

cout << "Element not found" << endl; }

return 0;

Output:

Binary Search:

Code:

#include <iostream>

using namespace std;

int binarySearch(int arr[], int n, int key) {

int low = 0, high = n - 1;

while (low <= high) {

int mid = low + (high - low) / 2;

if (arr[mid] == key) {

return mid;

} else if (arr[mid] < key) {

low = mid + 1;

} else { high = mid – 1; } }


return -1;}

int main() {

int n, key;

cout << "Enter the size of the array: ";

cin >> n;

int arr[n];

cout << "Enter " << n << " sorted elements: ";

for (int i = 0; i < n; i++) {

cin >> arr[i];

cout << "Enter the element to search: ";

cin >> key;

int result = binarySearch(arr, n, key);

if (result != -1) {

cout << "Element found at position " << result << endl;

} else {

cout << "Element not found" << endl;

} 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>

using namespace std;

int main() {

int n;

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]; }

for (int i = 0; i < n - 1; i++) {

for (int j = 0; j < n - i - 1; j++) {

if (arr[j] > arr[j + 1]) {

swap(arr[j], arr[j + 1]); }}}

cout << "Sorted array: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " ";

} cout << endl;

return 0;}

Output:
Insertion Sort:

Time Complexity:

 Best Case: O(n)O(n)O(n) (when the array is already sorted).


 Average and Worst Case: O(n2)O(n^2)O(n2) (when the array is reverse sorted or random).

Code:

#include <iostream>

using namespace std;

int main() {

int n;

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];

for (int i = 1; i < n; i++) {

int key = arr[i];

int j = i - 1;

while (j >= 0 && arr[j] > key) {

arr[j + 1] = arr[j];

j = j - 1;

arr[j + 1] = key; }
cout << "Sorted array: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " "; }

cout << endl;

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>

using namespace std;

int main() {

int n;

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];

for (int i = 0; i < n - 1; i++) {

int minIndex = i;

for (int j = i + 1; j < n; j++) {

if (arr[j] < arr[minIndex]) {

minIndex = j;

if (minIndex != i) {

swap(arr[i], arr[minIndex]); }}

cout << "Sorted array: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " ";}

cout << endl;

return 0;

Output:

Quick Sort

 Description: Divide and conquer algorithm that selects a pivot and partitions the array around it.
 Time Complexity: O(nlog⁡n)O(n \log n)O(nlogn) (average), O(n2)O(n^2)O(n2) (worst).
Code:

#include <iostream>

using namespace std;

int partition(int arr[], int low, int high) {

int pivot = arr[high];

int i = low - 1;

for (int j = low; j < high; j++) {

if (arr[j] <= pivot) {

i++;

swap(arr[i], arr[j]);

swap(arr[i + 1], arr[high]);

return i + 1;

void quickSort(int arr[], int low, int high) {

if (low < high) {

int pi = partition(arr, low, high);

quickSort(arr, low, pi - 1);

quickSort(arr, pi + 1, high);

int main() {

int n;

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];

quickSort(arr, 0, n - 1);

cout << "Sorted array: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " ";

}cout << endl;

return 0;

Output:

Merge Sort

 Description: Recursively divide the array into halves, sort, and merge them.
 Time Complexity: O(nlog⁡n)O(n \log n)O(nlogn)

Code:

#include <iostream>

using namespace std;

void merge(int arr[], int left, int mid, int right) {

int n1 = mid - left + 1;

int n2 = right - mid;


int L[n1], R[n2];

for (int i = 0; i < n1; i++) {

L[i] = arr[left + i];

for (int j = 0; j < n2; j++) {

R[j] = arr[mid + 1 + j];

int i = 0, j = 0, k = left;

while (i < n1 && j < n2) {

if (L[i] <= R[j]) {

arr[k] = L[i];

i++;

} else {

arr[k] = R[j];

j++;

k++;

while (i < n1) {

arr[k] = L[i];

i++;

k++;
}

while (j < n2) {

arr[k] = R[j];

j++;

k++;

void mergeSort(int arr[], int left, int right) {

if (left < right) {

int mid = left + (right - left) / 2;

mergeSort(arr, left, mid);

mergeSort(arr, mid + 1, right);

merge(arr, left, mid, right);

int main() {

int n;

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];

mergeSort(arr, 0, n - 1);

cout << "Sorted array: ";

for (int i = 0; i < n; i++) {

cout << arr[i] << " ";

cout << endl;

return 0;

Output:

Stack in Data Structures and Algorithms (DSA)

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:

1. Push: Add an element to the top of the stack.


2. Pop: Remove the element from the top of the stack

Basic Stack 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)

 Description: Add an element to the top of the stack.


 Time Complexity: O(1)O(1)O(1)

Code:

#include <iostream>

using namespace std;

class Stack {

int *arr;

int top;

int capacity;

public:

Stack(int size) {

capacity = size;

arr = new int[capacity];

top = -1;

void push(int value) {

if (top == capacity - 1) {

cout << "Stack Overflow" << endl;

return; }

arr[++top] = value;

void display() {

if (top == -1) {
cout << "Stack is empty" << endl;

return;

for (int i = 0; i <= top; i++) {

cout << arr[i] << " "; }

cout << endl;

~Stack() {

delete[] arr; }

};

int main() {

int n;

cout << "Enter the size of the stack: ";

cin >> n;

Stack stack(n);

int value;

cout << "Enter values to push into the stack (enter -1 to stop):" << endl;

while (true) {

cin >> value;

if (value == -1) break;

stack.push(value);

} cout << "Stack elements: ";

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:

void push(int item) {

stack.push(item);

void pop() {

if (!isEmpty()) {

stack.pop();

} else {

std::cout << "Stack is empty!" << std::endl;


}

int peek() {

if (!isEmpty()) {

return stack.top();

} else {

std::cout << "Stack is empty!" << std::endl;

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: " << stack.peek() << std::endl;


stack.pop();

std::cout << "Peek after pop: " << stack.peek() << std::endl;

return 0;

Output:

isEmpty

 Description: Check if the stack is empty.


 Time Complexity: O(1)O(1)O(1)

Code:

#include <iostream>

using namespace std;

class Stack {

int *arr;

int top;

int capacity;

public:

Stack(int size) {

capacity = size;

arr = new int[capacity];

top = -1;

}
bool isEmpty() {

return top == -1;

void push(int value) {

if (top == capacity - 1) {

cout << "Stack Overflow" << endl;

return;

arr[++top] = value;

void display() {

if (top == -1) {

cout << "Stack is empty" << endl;

return;

for (int i = 0; i <= top; i++) {

cout << arr[i] << " ";

cout << endl;

~Stack() {

delete[] arr;

};

int main() {

int n;

cout << "Enter the size of the stack: ";

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.

Key Characteristics of Queues

1. FIFO Principle: The order of insertion determines the order of removal.


o Elements are added at the rear (enqueue) and removed from the front (dequeue).

Time Complexity:

2. Enqueue and Dequeue: O(1) in typical implementations.


3. Peek: O(1).
4. Searching: O(n), as a queue does not support direct access

Basic Operations:

 Enqueue: Add an element to the rear of the queue.


 Dequeue: Remove an element from the front of the queue.
 Peek/Front: View the front element without removing it.
 isEmpty: Check if the queue is empty.
 isFull (optional in bounded queues): Check if the queue has reached its capacity.

Code:

#include <iostream>
#include <vector>

using namespace std;

class Queue {

vector<int> queue;

int capacity;

public:

Queue(int cap = -1) : capacity(cap) {}

void enqueue(int item) {

if (capacity == -1 || queue.size() < capacity)

queue.push_back(item); }

int dequeue() {

if (!isEmpty()) {

int front = queue.front();

queue.erase(queue.begin());

return front; }

return -1;

} int peek() {

if (!isEmpty())

return queue.front();

return -1;

bool isEmpty() {

return queue.empty(); }
bool isFull() {

return capacity != -1 && queue.size() == capacity; }};

int main() {

Queue q(5);

q.enqueue(10);

q.enqueue(20);

q.enqueue(30);

cout << "Front element: " << q.peek() << endl;

cout << "Dequeue: " << q.dequeue() << endl;

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 << "Dequeue: " << q.dequeue() << endl;

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.

Key Characteristics of Circular Queue

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.

2. Efficient Memory Utilization:


o Unlike a linear queue, which may leave unused spaces after elements are dequeued, a
circular queue reuses these spaces.

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).

4. Full vs. Empty Queue:


o A circular queue is considered full when: (rear+1)%size==front(rear + 1) \% size ==
front(rear+1)%size==front
o It is empty when: front==rearfront == rearfront==rear

Basic Operations

Enqueue (Insert an Element)

Dequeue (Remove an Element)

Peek (View the Front Element)

isEmpty (Check if the Queue is Empty)

isFull (Check if the Queue is Full)


Code
#include <iostream>

using namespace std;

class Queue {

int* queue;

int front, rear, capacity;

public:

Queue(int cap) : capacity(cap), front(0), rear(-1) {

queue = new int[capacity];

~Queue() {

delete[] queue; }

void enqueue(int item) {

if (!isFull()) {

rear = (rear + 1) % capacity;

queue[rear] = item; }}

int dequeue() {

if (!isEmpty()) {

int item = queue[front];

front = (front + 1) % capacity;

return item; }

return -1;}

int peek() {

if (!isEmpty())

return queue[front];

return -1; }

bool isEmpty() {

return front == (rear + 1) % capacity; }


bool isFull() {

return front == (rear + 2) % capacity;

}};

int main() {

Queue q(5);

q.enqueue(10);

q.enqueue(20);

q.enqueue(30);

q.enqueue(40);

cout << "Front element: " << q.peek() << endl;

cout << "Dequeue: " << q.dequeue() << endl;

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 << "Dequeue: " << q.dequeue() << endl;

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:

1. Data: The value stored in the node.


2. Pointer (Next): A reference to the next node in the list.

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

Traversal (Iterate through the List)

Insertion (Add a New Node)

At the End

Code
#include <iostream>

using namespace std;

class Node {

public:

int data;

Node* next;

Node(int val) {

data = val;

next = nullptr; }};

class LinkedList {

Node* head;

public:

LinkedList() {

head = nullptr;

void insertAtEnd(int val) {


Node* newNode = new Node(val);

if (head == nullptr) {

head = newNode;

} else {

Node* temp = head;

while (temp->next != nullptr) {

temp = temp->next;

temp->next = newNode; }

void traverse() {

Node* temp = head;

while (temp != nullptr) {

cout << temp->data << " ";

temp = temp->next; }

cout << endl; }};

int main() {

LinkedList list;

list.insertAtEnd(10);

list.insertAtEnd(20);

list.insertAtEnd(30);

cout << "Linked List: ";

list.traverse();

list.insertAtEnd(40);

list.insertAtEnd(50);

cout << "After Insertion: ";

list.traverse();

return 0;

}
OUTPUT

You might also like