Searching Algorithm:
Searching algorithm is the process of finding the existence of a specific element, within
an array, list, or tree. It is a fundamental operation which is used to retrieve data efficiently.
Types of Searching Algorithms
1. Linear Search 2. Binary Search
1. Linear Search : Linear Search is a basic searching algorithm that checks each element
of the data structure sequentially until the desired element is found.
Working of Linear Search :
i) Start from the first element.
ii) Compare each element with the key.
iii) If a match is found, return its position.
iv) If no match is found after checking all elements, return "Not Found".
Time Complexity :
• Best Case: O(1) → if key is the first element
• Worst Case: O(n) → if key is the last element or not present
• Space Complexity: O(1)
Prog.
#include <stdio.h>
void linearSearch(int arr[], int n, int key) {
int i;
for (i = 0; i < n; i++) {
if (arr[i] == key) {
printf("Element found at index %d (position %d).\n", i, i + 1);
return;
}
}
// If element is not found
printf("Element not found in the array.\n");
}
void main() {
int n, key, i;
// Input the number of elements
printf("Enter the number of elements in the array: ");
scanf("%d", &n);
int arr[n];
// Input elements of the array
printf("Enter %d elements:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Input the element to search
printf("Enter the element to search: ");
scanf("%d", &key);
// Call the linear search function
linearSearch(arr, n, key);
}
2. Binary Search : Binary Search is an efficient searching algorithm that finds the
position of a target value in a sorted array by repeatedly dividing the search interval
in half.
Note : It works only on arrays that are sorted in ascending or descending order.
Working of Binary Search :
Start with a sorted array.
Binary search only works on data that is already in ascending or descending order.
Initialize two variables:
low = 0 (start index)
high = n - 1 (end index)
Repeat while low <= high:
a. Calculate the middle index:
mid = (low + high) / 2
b. Compare the middle element arr[mid] with the key:
If arr[mid] == key:
→ Element is found at index mid
If arr[mid] < key:
→ Search in the right half by setting low = mid + 1
If arr[mid] > key:
→ Search in the left half by setting high = mid - 1
If the loop ends without finding the element:
→ The element is not present in the array.
Example:
Array: 10, 20, 30, 40, 50
Search Key: 30
• Step 1: low = 0, high = 4, mid = 2
• Step 2: arr[2] = 30 → Element found!
Time Complexity of Binary Search :
Binary Search reduces the search space by half with each step. So, for an array of n elements,
it will take at most log₂(n) steps.
Time Complexities
Case Time Complexity Explanation
Best O(1) If the element is found at the first middle check
Average O(log n) Each comparison cuts the array in half
Worst O(log n) Element is at the end or not present at all
Prog.
#include <stdio.h>
void binarySearch(int arr[], int n, int key) {
int low = 0;
int high = n - 1;
int mid;
while (low <= high) {
mid = (low + high) / 2;
if (arr[mid] == key) {
printf("Element found at index %d (position %d).\n", mid, mid + 1);
return;
} else if (arr[mid] < key) {
low = mid + 1;
} else {
high = mid - 1;
}
}
// If not found
printf("Element not found in the array.\n");
}
void main() {
int n, key;
// Input array size
printf("Enter the number of elements in the array: ");
scanf("%d", &n);
int arr[n];
// Input sorted array elements
printf("Enter %d sorted elements (ascending order):\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Input key to search
printf("Enter the element to search: ");
scanf("%d", &key);
// Call binary search
binarySearch(arr, n, key);
}
Sorting Algorithms:
Sorting algorithms are methods used to arrange the elements of a list or array in a specific
order — typically ascending or descending.
Sorting helps in organizing data and makes searching and other operations more efficient.
Types of Sorting Algorithms :
Sorting algorithms can be classified based on technique, complexity, and stability. Here's a
basic list of common types:
1. Bubble Sort 2. Selection Sort 3. Insertion Sort
4. Merge Sort 5. Quick Sort 6. Heap Sort
1. Bubble Sort : Bubble Sort is a simple sorting algorithm that works by repeatedly
swapping adjacent elements if they are in the wrong order.
It continues doing this until the entire array is sorted.
Working Process of Bubble Sort :
Start from the beginning of the array.
Compare the first and second elements:
o If the first is greater than the second, swap them.
Move to the next pair, compare and swap if needed.
Repeat this process for all elements.
After each full pass, the largest unsorted element "bubbles up" to its correct
position.
Repeat the passes until the array is sorted.
Example
Array: 5 3 8 4 2
• Pass 1: 3 5 4 2 8
• Pass 2: 3 4 2 5 8
• Pass 3: 3 2 4 5 8
• Pass 4: 2 3 4 5 8 =➔Sorted!
Time Complexity
Case Time Complexity
Best O(n) (if already sorted)
Average O(n²)
Worst O(n²)
Prog.
#include <stdio.h>
void bubbleSort(int arr[], int n) {
int i, j, temp;
for (i = 0; i < n - 1; i++) {
// Flag to check if any swapping happened
int swapped = 0;
for (j = 0; j < n - i - 1; j++) {
// Compare adjacent elements
if (arr[j] > arr[j + 1]) {
// Swap if elements are in wrong order
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = 1;
}
}
// If no two elements were swapped, the array is already sorted
if (swapped == 0) {
break;
}
}
}
void main() {
int n, i;
// Input number of elements
printf("Enter the number of elements: ");
scanf("%d", &n);
int arr[n];
// Input array elements
printf("Enter %d elements:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Call the bubble sort function
bubbleSort(arr, n);
// Print sorted array
printf("Sorted array in ascending order:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
2. Selection Sort : Selection Sort is a simple sorting algorithm that works by repeatedly
finding the smallest (or largest) element from the unsorted part of the array and swapping it
with the first unsorted element.
It divides the array into two parts:
• Sorted part (built from the front)
• Unsorted part (remaining elements)
Working Process of Selection Sort :
Start with the first element.
Find the smallest element in the unsorted part of the array.
Swap it with the first unsorted element.
Move to the next position and repeat the process until the array is fully sorted
Example
Array: 29, 10, 14, 37, 14
• Pass 1: Find minimum → 10 → Swap with 29 → 10, 29, 14, 37, 14
• Pass 2: Min is 14 → Swap with 29 → 10, 14, 29, 37, 14
• Pass 3: Min is 14 → Swap with 29 → 10, 14, 14, 37, 29
• Pass 4: Min is 29 → Swap with 37 → 10, 14, 14, 29, 37 ➔ Sorted
Time Complexity :
Case Time Complexity
Best O(n²)
Average O(n²)
Worst O(n²)
Prog.
#include <stdio.h>
void selectionSort(int arr[], int n) {
int i, j, minIndex, temp;
for (i = 0; i < n - 1; i++) {
minIndex = i;
// Find the index of the smallest element in the unsorted part
for (j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// Swap the found minimum element with the first unsorted element
if (minIndex != i) {
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
}
}
void main() {
int n, i;
// Input array size
printf("Enter the number of elements: ");
scanf("%d", &n);
int arr[n];
// Input array elements
printf("Enter %d elements:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Sort the array using Selection Sort
selectionSort(arr, n);
// Print sorted array
printf("Sorted array in ascending order:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
3. Insertion Sort : Insertion Sort is a sorting algorithm in which elements are picked
one by one and inserted into their correct position in the already sorted part of the
array.
It maintains a sorted subarray on the left side and gradually inserts each new element
into its correct place.
Working Process of Insertion Sort :
Assume the first element is already sorted.
Take the next element and compare it with the elements in the sorted part.
Shift elements to the right until the correct position is found.
Insert the current element into that position.
Repeat for all remaining elements.
Example
Array: 5, 3, 4, 1
• Pass 1: 3 inserted before 5 → 3, 5, 4, 1
• Pass 2: 4 inserted between 3 and 5 → 3, 4, 5, 1
• Pass 3: 1 inserted at the beginning → 1, 3, 4, 5 ➔ Sorted
Time Complexity
Case Time Complexity
O(n) (already
Best
sorted)
Average O(n²)
Worst O(n²)
#include <stdio.h>
void insertionSort(int arr[], int n) {
int i, j, key;
for (i = 1; i < n; i++) {
key = arr[i];
j = i - 1;
// Move elements that are greater than key
// to one position ahead of their current position
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}
// Insert the key into its correct position
arr[j + 1] = key;
}
}
void main() {
int n, i;
// Input number of elements
printf("Enter the number of elements: ");
scanf("%d", &n);
int arr[n];
// Input elements
printf("Enter %d elements:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Sort the array using Insertion Sort
insertionSort(arr, n);
// Print sorted array
printf("Sorted array in ascending order:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
4. Merge Sort : Merge Sort is a divide and conquer sorting algorithm that divides the
array into two halves, sorts them recursively, and then merges the sorted halves to get
the final sorted array.
Working Process of Merge Sort :
Divide the array into two halves.
Recursively sort both halves.
Merge the two sorted halves into one sorted array.
Example
Array: 6, 3, 8, 2
1. Divide: [6, 3] and [8, 2]
2. Divide again: [6] [3] [8] [2]
3. Merge: [3, 6] and [2, 8]
4. Final merge: [2, 3, 6, 8] ➔ Sorted
Time Complexity :
Time
Case
Complexity
Best O(n log n)
Average O(n log n)
Worst O(n log n)
Prog.
#include <stdio.h>
// Merge two halves of the array
void merge(int arr[], int left, int mid, int right) {
int i, j, k;
int n1 = mid - left + 1; // Size of left half
int n2 = right - mid; // Size of right half
// Temporary arrays
int L[n1], R[n2];
// Copy data to temp arrays
for (i = 0; i < n1; i++)
L[i] = arr[left + i];
for (j = 0; j < n2; j++)
R[j] = arr[mid + 1 + j];
// Merge the temp arrays back into arr[]
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++;
}
// Copy remaining elements of L[]
while (i < n1) {
arr[k] = L[i];
i++;
k++;
}
// Copy remaining elements of R[]
while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}
// Recursive merge sort function
void mergeSort(int arr[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
// Sort first and second halves
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// Merge the sorted halves
merge(arr, left, mid, right);
}
}
void main() {
int n, i;
printf("Enter the number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements:\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Call merge sort
mergeSort(arr, 0, n - 1);
// Print sorted array
printf("Sorted array in ascending order:\n");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
5. Quick Sort : Quick Sort is a fast and efficient divide and conquer sorting algorithm
that works by selecting a pivot element, partitioning the array around the pivot, and
then recursively sorting the left and right subarrays.
Working Process of Quick Sort :
Choose a pivot element from the array (commonly first, last, or middle element).
Partition the array:
Place elements smaller than pivot on the left,
Place elements greater than pivot on the right.
Recursively apply Quick Sort on the left and right parts.
The array becomes sorted after all partitions are complete.
Example
Array: 5, 3, 8, 4, 2
• Choose pivot = 2
→ Partition: [2] | [3, 8, 4, 5]
• Choose pivot = 3
→ Partition: [2, 3] | [4, 8, 5]
• Continue recursively
→ Final sorted: [2, 3, 4, 5, 8]
Time Complexity
Case Time Complexity
Best O(n log n)
Average O(n log n)
Worst O(n²) → happens when array is already sorted and poor pivot is chosen
#include <stdio.h>
// Function to swap two elements
void swap(int arr[], int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// Partition function using last element as pivot
int partition(int arr[], int low, int high) {
int pivot = arr[high]; // Pivot is the last element
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
swap(arr, i, j);
}
}
swap(arr, i + 1, high); // Place pivot in correct position
return i + 1;
}
// Quick Sort function
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1); // Sort left part
quickSort(arr, pi + 1, high); // Sort right part
}
}
void main() {
int n;
printf("Enter the number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Call Quick Sort
quickSort(arr, 0, n - 1);
// Print sorted array
printf("Sorted array in ascending order:\n");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}
6. Heap Sort : Heap Sort is a comparison-based sorting algorithm that uses a binary heap
data structure (usually a max heap) to sort elements.
It builds a heap from the input data, then repeatedly removes the maximum element from the
heap and places it at the end of the array.
Q. What is a Heap?
Ans : A heap is a special binary tree:
o Max Heap: Each parent node is greater than or equal to its children.
o Min Heap: Each parent node is less than or equal to its children.
• In Heap Sort, we use a Max Heap to get the largest element at the root.
Working Process of Heap Sort :
Build a Max Heap from the array.
The largest element is now at the root (index 0).
Swap it with the last element of the array.
Reduce the heap size by 1 (ignore the last sorted element).
Heapify the root again to maintain the heap property.
Repeat steps 3–5 until the entire array is sorted.
Example (Array):
Input: 4, 10, 3, 5, 1
1. Build Max Heap → 10, 5, 3, 4, 1
2. Swap 10 with 1 → 1, 5, 3, 4, 10
3. Heapify again → 5, 4, 3, 1, 10
4. Repeat...
Final sorted array: 1, 3, 4, 5, 10
Time Complexity
Time
Case
Complexity
Best O(n log n)
Average O(n log n)
Worst O(n log n)
Prog .
#include <stdio.h>
// Function to heapify a subtree rooted at index i
void heapify(int arr[], int n, int i) {
int largest = i; // Initialize largest as root
int left = 2 * i + 1; // left child
int right = 2 * i + 2; // right child
// If left child is larger than root
if (left < n && arr[left] > arr[largest]) {
largest = left;
}
// If right child is larger than largest so far
if (right < n && arr[right] > arr[largest]) {
largest = right;
}
// If largest is not root
if (largest != i) {
// Swap arr[i] and arr[largest]
int temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
// Recursively heapify the affected sub-tree
heapify(arr, n, largest);
}
}
// Main function to do heap sort
void heapSort(int arr[], int n) {
// Build a max heap
for (int i = n / 2 - 1; i >= 0; i--) {
heapify(arr, n, i);
}
// One by one extract elements from heap
for (int i = n - 1; i >= 0; i--) {
// Move current root to end
int temp = arr[0];
arr[0] = arr[i];
arr[i] = temp;
// call max heapify on the reduced heap
heapify(arr, i, 0);
}
}
void main() {
int n;
printf("Enter number of elements: ");
scanf("%d", &n);
int arr[n];
printf("Enter %d elements:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
// Perform heap sort
heapSort(arr, n);
// Print sorted array
printf("Sorted array in ascending order:\n");
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
}