0% found this document useful (0 votes)
7 views19 pages

Lab Manual

The document outlines a 10-week curriculum focused on C++ programming, covering fundamental concepts such as classes, pointers, and data structures including arrays, linked lists, stacks, queues, and trees. It also includes sorting and searching algorithms, as well as advanced topics like graphs and priority queues. Each week introduces new concepts and implementations, providing a comprehensive guide to mastering C++ programming.

Uploaded by

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

Lab Manual

The document outlines a 10-week curriculum focused on C++ programming, covering fundamental concepts such as classes, pointers, and data structures including arrays, linked lists, stacks, queues, and trees. It also includes sorting and searching algorithms, as well as advanced topics like graphs and priority queues. Each week introduces new concepts and implementations, providing a comprehensive guide to mastering C++ programming.

Uploaded by

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

1. Week 1: Introduction to C++, classes, structures, and pointers.

START
DECLARE int x = 10; // Simple integer variable
DECLARE float y = 15.5; // Simple float variable
// Classes and Structures
DEFINE class MyClass
DECLARE int a, b;
FUNCTION MyClass(int x, int y)
a = x;
b = y;
END
FUNCTION int sum()
RETURN a + b;
END
END

MyClass obj1(5, 10);


PRINT obj1.sum()
// Pointers
DECLARE int* ptr = &x; // Pointer to x
PRINT *ptr // Dereferencing the pointer to get the value of x
END
2. Week 2: Array ADT and String ADT. Implementing simple sorting algorithms.
START
// Array ADT
DEFINE array A[5] = {5, 1, 3, 9, 7};

// Simple Sorting Algorithms: Bubble Sort


FUNCTION BubbleSort(array A)
DECLARE int n = length(A);
FOR i FROM 0 TO n-1
FOR j FROM 0 TO n-i-1
IF A[j] > A[j+1]
SWAP A[j], A[j+1]
END
END
END
END

CALL BubbleSort(A)
PRINT A
END
3. Week 3: Selection sort, Bubble sort, Insertion sort.
START
// Selection Sort
FUNCTION SelectionSort(array A)
Prepared: By Medhanye

1
DECLARE int n = length(A);
FOR i FROM 0 TO n-1
DECLARE int minIdx = i;
FOR j FROM i+1 TO n
IF A[j] < A[minIdx]
minIdx = j;
END
END
SWAP A[i], A[minIdx]
END
END

// Insertion Sort
FUNCTION InsertionSort(array A)
DECLARE int n = length(A);
FOR i FROM 1 TO n-1
DECLARE int key = A[i];
DECLARE int j = i-1;
WHILE j >= 0 AND A[j] > key
A[j+1] = A[j]
j = j-1
END
A[j+1] = key
END
END
END

4. Week 4: Implementing Searching Algorithms: Linear search and Binary search.


START
// Linear Search
FUNCTION LinearSearch(array A, int target)
DECLARE int n = length(A);
FOR i FROM 0 TO n-1
IF A[i] == target
RETURN i;
END
END
RETURN -1; // Not found
END

// Binary Search (requires sorted array)


FUNCTION BinarySearch(array A, int target)
DECLARE int low = 0;
DECLARE int high = length(A) - 1;
WHILE low <= high

Prepared: By Medhanye

2
DECLARE int mid = (low + high) / 2;
IF A[mid] == target
RETURN mid;
ELSE IF A[mid] < target
low = mid + 1;
ELSE
high = mid - 1;
END
END
RETURN -1; // Not found
END
END

5. Week 5: Implementing Linked Lists: Singly linked list, Doubly linked list, Circular linked list.
START
// Singly Linked List
DEFINE class Node
DECLARE int data;
DECLARE Node* next;
END

DEFINE class SinglyLinkedList


DECLARE Node* head;

FUNCTION SinglyLinkedList()
head = NULL;
END

FUNCTION InsertAtEnd(int value)


DECLARE Node* newNode = new Node();
newNode->data = value;
newNode->next = NULL;
IF head == NULL
head = newNode;
ELSE
DECLARE Node* temp = head;
WHILE temp->next != NULL
temp = temp->next;
END
temp->next = newNode;
END
END
END

// Doubly Linked List (add prev pointer)

Prepared: By Medhanye

3
DEFINE class DoublyLinkedList
DECLARE Node* head;
FUNCTION InsertAtEnd(int value)
DECLARE Node* newNode = new Node();
newNode->data = value;
newNode->next = NULL;
newNode->prev = NULL;
IF head == NULL
head = newNode;
ELSE
DECLARE Node* temp = head;
WHILE temp->next != NULL
temp = temp->next;
END
temp->next = newNode;
newNode->prev = temp;
END
END
END

// Circular Linked List (last node points to the head)


DEFINE class CircularLinkedList
DECLARE Node* head;

FUNCTION InsertAtEnd(int value)


DECLARE Node* newNode = new Node();
newNode->data = value;
newNode->next = head;
IF head == NULL
head = newNode;
ELSE
DECLARE Node* temp = head;
WHILE temp->next != head
temp = temp->next;
END
temp->next = newNode;
END
END
END
END

6. Week 6: Stack Implementation: Array-based and Linked List-based.


START
// Array-based Stack
DEFINE class StackArray

Prepared: By Medhanye

4
DECLARE int MAX_SIZE = 100;
DECLARE int arr[MAX_SIZE];
DECLARE int top;

FUNCTION StackArray()
top = -1;
END

FUNCTION Push(int value)


IF top < MAX_SIZE - 1
top = top + 1;
arr[top] = value;
ELSE
PRINT "Stack Overflow";
END
END

FUNCTION Pop()
IF top > -1
RETURN arr[top--];
ELSE
PRINT "Stack Underflow";
RETURN -1;
END
END
END

// Linked List-based Stack


DEFINE class StackLinkedList
DECLARE Node* top;

FUNCTION Push(int value)


DECLARE Node* newNode = new Node();
newNode->data = value;
newNode->next = top;
top = newNode;
END

FUNCTION Pop()
IF top != NULL
DECLARE int value = top->data;
top = top->next;
RETURN value;
ELSE
PRINT "Stack Underflow";
RETURN -1;

Prepared: By Medhanye

5
END
END
END
END

7. Week 7: Queue Implementation: Array-based and Linked List-based.


START
// Array-based Queue
DEFINE class QueueArray
DECLARE int MAX_SIZE = 100;
DECLARE int arr[MAX_SIZE];
DECLARE int front, rear;

FUNCTION QueueArray()
front = -1;
rear = -1;
END
FUNCTION Enqueue(int value)
IF rear < MAX_SIZE - 1
rear = rear + 1;
arr[rear] = value;
IF front == -1
front = 0;
END
ELSE
PRINT "Queue Overflow";
END
END

FUNCTION Dequeue()
IF front != -1
DECLARE int value = arr[front];
front = front + 1;
RETURN value;
ELSE
PRINT "Queue Underflow";
RETURN -1;
END
END
END

// Linked List-based Queue


DEFINE class QueueLinkedList
DECLARE Node* front, rear;
FUNCTION Enqueue(int value)

Prepared: By Medhanye

6
DECLARE Node* newNode = new Node();
newNode->data = value;
newNode->next = NULL;
IF rear == NULL
front = newNode;
rear = newNode;
ELSE
rear->next = newNode;
rear = newNode;
END
END
FUNCTION Dequeue()
IF front != NULL
DECLARE int value = front->data;
front = front->next;
RETURN value;
ELSE
PRINT "Queue Underflow";
RETURN -1;
END
END
END
END

8. Week 8: Double-ended Queue (Deque) and Priority Queue


Class PriorityQueue:
Initialize():
heap = empty list (This will store the elements)
IsEmpty():
return length of heap == 0
Parent(i):
return (i - 1) // 2
LeftChild(i):
return 2 * i + 1
RightChild(i):
return 2 * i + 2
Swap(i, j):
temp = heap[i]
heap[i] = heap[j]
heap[j] = temp
Insert(value):
append value to heap (insert at the end)
current = length of heap - 1
while current > 0 and heap[current] > heap[Parent(current)]:
Swap(current, Parent(current))

Prepared: By Medhanye

7
current = Parent(current)
ExtractMax():
if IsEmpty():
print("Queue is empty!")
return None
maxValue = heap[0]
heap[0] = heap[length of heap - 1]
remove last element from heap
MaxHeapify(0)
return maxValue
MaxHeapify(i):
left = LeftChild(i)
right = RightChild(i)
largest = i

if left < length of heap and heap[left] > heap[largest]:


largest = left

if right < length of heap and heap[right] > heap[largest]:


largest = right
if largest != i:
Swap(i, largest)
MaxHeapify(largest)

PeekMax():
if IsEmpty():
print("Queue is empty!")
return None
return heap[0]

Display():
print("Priority Queue:")
for element in heap:
print(element)
Week 9: Implementing Binary Search Trees.
Class TreeNode:
Initialize(value):
this.value = value
this.left = None
this.right = None

Class BinarySearchTree:
Initialize():
this.root = None
Insert(value):
if root is None:
Prepared: By Medhanye

8
root = TreeNode(value)
else:
InsertRec(root, value)

InsertRec(node, value):
if value < node.value:
if node.left is None:
node.left = TreeNode(value)
else:
InsertRec(node.left, value)
else:
if node.right is None:
node.right = TreeNode(value)
else:
InsertRec(node.right, value)
Search(value):
return SearchRec(root, value)
SearchRec(node, value):
if node is None:
return False
if value == node.value:
return True
if value < node.value:
return SearchRec(node.left, value)
else:
return SearchRec(node.right, value)
Delete(value):
root = DeleteRec(root, value)
DeleteRec(node, value):
if node is None:
return node
if value < node.value:
node.left = DeleteRec(node.left, value)
else if value > node.value:
node.right = DeleteRec(node.right, value)
else:
if node.left is None:
return node.right
else if node.right is None:
return node.left
temp = FindMin(node.right)
node.value = temp.value
node.right = DeleteRec(node.right, temp.value)
return node
FindMin(node):
Prepared: By Medhanye

9
current = node
while current.left is not None:
current = current.left
return current
InOrderTraversal():
InOrderRec(root)

InOrderRec(node):
if node is not None:
InOrderRec(node.left)
print(node.value)
InOrderRec(node.right)
PreOrderTraversal():
PreOrderRec(root)

PreOrderRec(node):
if node is not None:
print(node.value)
PreOrderRec(node.left)
PreOrderRec(node.right)
PostOrderTraversal():
PostOrderRec(root)

PostOrderRec(node):
if node is not None:
PostOrderRec(node.left)
PostOrderRec(node.right)
print(node.value)
Display():
InOrderTraversal()
Week 10: Graphs: Implementing Graph Traversal Algorithms.
Class Graph:
Initialize():
this.graph = {} # An adjacency list
AddEdge(u, v):
if u not in graph:
graph[u] = []
graph[u].append(v)
if v not in graph:
graph[v] = []
graph[v].append(u)

BFS(start):
visited = set() # Set of visited nodes
queue = Queue() # Queue for BFS
Prepared: By Medhanye

10
queue.enqueue(start)
visited.add(start)
while not queue.isEmpty():
node = queue.dequeue()
print(node) # Process the node (e.g., print it)
for neighbor in graph[node]:
if neighbor not in visited:
visited.add(neighbor)
queue.enqueue(neighbor)
Week 11: Advanced Sorting Algorithms: Shell sort, Heap sort.

1. Shell Sort

Shell Sort is an extension of the insertion sort algorithm that allows the exchange of items that
are far apart. It works by comparing elements separated by a gap and reducing the gap
progressively until the gap becomes 1 (in which case, the algorithm becomes an insertion sort)
Function ShellSort(array):
# Start with a large gap and reduce the gap after each iteration
gap = length(array) // 2 # Initial gap size
while gap > 0:
# Perform a modified insertion sort with the given gap
for i = gap to length(array) - 1:
temp = array[i]
j=i
# Move elements that are greater than temp to one position ahead
while j >= gap and array[j - gap] > temp:
array[j] = array[j - gap]
j = j - gap
array[j] = temp
# Reduce the gap size
gap = gap // 2

Explanation:

 Gap Sequence: The gap starts from half the array size and is reduced by half after each iteration.
 Modified Insertion Sort: For each gap, the array is sorted as if it were made up of several
subarrays where elements are gap positions apart. This is a more efficient approach than the
standard insertion sort.
 The process continues until the gap becomes 1, at which point the algorithm becomes a
standard insertion sort

2. Heap Sort

Heap Sort is a comparison-based sorting algorithm that uses a binary heap data structure. It first
builds a max-heap (or min-heap) from the input data and then repeatedly extracts the maximum
Prepared: By Medhanye

11
element from the heap, placing it at the end of the array. The heap property ensures that the
largest element is always at the root of the heap.
Function HeapSort(array):
n = length(array)
# Step 1: Build a max-heap
for i = n // 2 - 1 to 0: # Start from the last non-leaf node
MaxHeapify(array, n, i)
# Step 2: Extract elements from the heap
for i = n - 1 to 1:
# Swap the current root (maximum) with the last element
Swap(array[0], array[i])
# Call MaxHeapify on the reduced heap
MaxHeapify(array, i, 0)
Function MaxHeapify(array, n, i):
largest = i
left = 2 * i + 1 # Left child
right = 2 * i + 2 # Right child
# Find the largest element among the root, left child, and right child
if left < n and array[left] > array[largest]:
largest = left
if right < n and array[right] > array[largest]:
largest = right
# If the largest element is not the root, swap and heapify the affected subtree
if largest != i:
Swap(array[i], array[largest])
MaxHeapify(array, n, largest)
Function Swap(a, b):
temp = a
a=b
b = temp

Explanation:

1. Max-Heap Construction:
o A binary heap is a complete binary tree where each parent node is greater than its child
nodes (for a max-heap).
o We build the heap by calling the MaxHeapify function starting from the last non-leaf
node (index n//2 - 1).

2. Heapify:
o In the MaxHeapify function, we ensure the subtree rooted at a given index maintains
the max-heap property. If the largest element is not at the root, we swap the root with
the largest child and recursively call MaxHeapify on the affected subtree.

3. Sorting:
Prepared: By Medhanye

12
o After building the max-heap, we repeatedly extract the maximum element (the root of
the heap), swap it with the last element of the array, reduce the heap size, and re-
heapify the root.

Week 12: Advanced Sorting Algorithms: Quick sort, Merge sort.

1. Quick Sort

Quick Sort is a divide-and-conquer algorithm that works by selecting a pivot element,


partitioning the array into two subarrays (elements less than the pivot and elements greater than
the pivot), and recursively sorting the subarrays.
Function QuickSort(array, low, high):
if low < high:
# Partition the array and get the pivot index
pivotIndex = Partition(array, low, high)
# Recursively sort the two subarrays
QuickSort(array, low, pivotIndex - 1) # Left subarray
QuickSort(array, pivotIndex + 1, high) # Right subarray
Function Partition(array, low, high):
# Choose the last element as pivot
pivot = array[high]
i = low - 1 # Index of smaller element
# Loop through the array and rearrange elements
for j = low to high - 1:
if array[j] <= pivot: # If current element is smaller than the pivot
i=i+1
Swap(array[i], array[j])
# Swap the pivot element with the element at (i + 1) position
Swap(array[i + 1], array[high])
return i + 1
Function Swap(a, b):
temp = a
a=b
b = temp

Explanation:

 Pivot Selection: In this pseudocode, we select the last element of the array as the pivot. Other
pivot selection strategies (e.g., first element, random element) can also be used.
 Partitioning: The Partition function rearranges the array such that elements less than the
pivot are on the left and elements greater than the pivot are on the right.
 Recursion: Once partitioned, the array is recursively divided into two subarrays and sorted until
the base case is reached (when the subarray has one or zero elements)
2. Merge Sort

Prepared: By Medhanye

13
Merge Sort is a stable, divide-and-conquer sorting algorithm that divides the array into two
halves, recursively sorts each half, and then merges the sorted halves back together.
Function MergeSort(array, left, right):

if left < right:

# Find the middle point

middle = (left + right) // 2

# Recursively sort the left and right subarrays

MergeSort(array, left, middle)

MergeSort(array, middle + 1, right)

# Merge the two sorted subarrays

Merge(array, left, middle, right)

Function Merge(array, left, middle, right):

# Create temporary subarrays

n1 = middle - left + 1

n2 = right - middle

leftArray = new array of size n1

rightArray = new array of size n2

# Copy data into temporary subarrays

for i = 0 to n1 - 1:

leftArray[i] = array[left + i]

for j = 0 to n2 - 1:

rightArray[j] = array[middle + 1 + j]

# Merge the temporary subarrays back into the original array

i = 0 # Initial index for left subarray


Prepared: By Medhanye

14
j = 0 # Initial index for right subarray

k = left # Initial index for the merged array

while i < n1 and j < n2:

if leftArray[i] <= rightArray[j]:

array[k] = leftArray[i]

i=i+1

else:

array[k] = rightArray[j]

j=j+1

k=k+1

# Copy remaining elements of leftArray if any

while i < n1:

array[k] = leftArray[i]

i=i+1

k=k+1

# Copy remaining elements of rightArray if any

while j < n2:

array[k] = rightArray[j]

j=j+1

k=k+1

Explanation:
Prepared: By Medhanye

15
 Divide: The array is recursively divided into two halves until each subarray has one or zero
elements.
 Merge: The Merge function merges two sorted subarrays into a single sorted array. It compares
the smallest unprocessed elements of both subarrays and builds the sorted array by repeatedly
selecting the smaller element.
 Stable Sort: Merge Sort is a stable sort, meaning that it preserves the relative order of elements
with equal values.
Week 13: Advanced Searching Algorithm: Hashing (Open and Closed Hashing).
Hashing is a technique used to efficiently search, insert, and delete data. It uses a hash function to map
data (keys) to fixed-size slots in an array (hash table). The two common types of hashing are Open
Hashing and Closed Hashing (also known as Open Addressing).

1. Open Hashing (Separate Chaining)

In Open Hashing, each slot of the hash table contains a linked list (or chain). Multiple elements
that hash to the same slot are stored in the linked list at that slot. This method handles collisions
by allowing multiple elements to exist at the same index.
Pseudocode for Open Hashing (Separate Chaining):
Function HashTableInsert(table, key, value):
index = HashFunction(key) # Calculate the hash index for the key
if table[index] is empty:
table[index] = new LinkedList() # Create a new linked list if empty
Insert into LinkedList(table[index], key, value)

Function HashTableSearch(table, key):


index = HashFunction(key) # Calculate the hash index for the key
if table[index] is not empty:
return LinkedListSearch(table[index], key)
return None # Key not found

Function HashTableDelete(table, key):


index = HashFunction(key) # Calculate the hash index for the key
if table[index] is not empty:
DeleteFromLinkedList(table[index], key)
else:
return "Key not found"

Function LinkedListInsert(list, key, value):


# Insert key-value pair at the beginning of the list
newNode = new Node(key, value)
newNode.next = list.head
list.head = newNode

Prepared: By Medhanye

16
Function LinkedListSearch(list, key):
current = list.head
while current is not null:
if current.key == key:
return current.value
current = current.next
return None # Key not found

Function DeleteFromLinkedList(list, key):


current = list.head
previous = null
while current is not null:
if current.key == key:
if previous is null:
list.head = current.next # Remove the first node
else:
previous.next = current.next # Remove the node
return
previous = current
current = current.next
return "Key not found"

Explanation:

 Insert: When inserting a key-value pair, we calculate the index using the hash function. If there
are no existing entries at the calculated index, we create a new linked list. Otherwise, we insert
the key-value pair into the linked list at that index.
 Search: To search for a key, we use the hash function to find the corresponding index and then
search the linked list at that index for the key.
 Delete: To delete a key, we use the hash function to find the corresponding index and then
delete the key from the linked list if it exists.

2. Closed Hashing (Open Addressing)

In Closed Hashing, all elements are stored directly in the hash table. When a collision occurs, we
probe for the next available slot based on a predefined strategy. The common probing techniques
are linear probing, quadratic probing, and double hashing.
Linear Probing (Closed Hashing)

In linear probing, when a collision occurs, the algorithm checks the next slot (index + 1) until an
empty slot is found.

Prepared: By Medhanye

17
Pseudocode for Linear Probing (Closed Hashing):
Function LinearProbingInsert(table, key, value):
index = HashFunction(key) # Calculate the hash index for the key
while table[index] is not empty:
if table[index].key == key: # Key already exists, update value
table[index].value = value
return
index = (index + 1) % table.size # Move to the next index
table[index] = new Entry(key, value) # Insert at empty slot

Function LinearProbingSearch(table, key):


index = HashFunction(key) # Calculate the hash index for the key
while table[index] is not empty:
if table[index].key == key:
return table[index].value
index = (index + 1) % table.size # Move to the next index
return None # Key not found

Function LinearProbingDelete(table, key):


index = HashFunction(key) # Calculate the hash index for the key
while table[index] is not empty:
if table[index].key == key:
table[index] = empty # Mark the slot as empty
return
index = (index + 1) % table.size # Move to the next index
return "Key not found"

Explanation:

 Insert: The function starts at the hash index and looks for an empty slot. If a collision occurs (slot
is not empty), it probes the next index in a linear manner.
 Search: Similar to insertion, but it returns the value associated with the key if found.
 Delete: Deletes the key and marks the slot as empty.

Advantages:

 Efficient use of space as all elements are stored in the hash table.
 Linear probing is simple to implement.

Disadvantages:

Prepared: By Medhanye

18
 Clustering: Consecutive elements may be hashed to the same location, leading to longer search
times.
 Deletion can cause gaps, requiring special handling during rehashing.

Prepared: By Medhanye

19

You might also like