Unit2 Algorithms
Unit2 Algorithms
Linear Search:-
The linear search algorithm is defined as a sequential search algorithm that starts at one end
and goes through each element of a list until the desired element is found; otherwise, the
search continues till the end of the dataset.
ASSI.PRO.UPEKSHA CHAUDHRI 1
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
ASSI.PRO.UPEKSHA CHAUDHRI 2
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
• Comparing key with next element arr[1]. SInce not equal, the iterator moves to the
next element as a potential match.
Step 2: Now when comparing arr[2] with key, the value matches. So the Linear Search
Algorithm will yield a successful message and return the index of the element when key is
found (here 2).
Example:-
#include <stdio.h>
int main() {
int n, i, search, array[100];
ASSI.PRO.UPEKSHA CHAUDHRI 3
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
return 0;
}
Time Complexity:
• Best Case: In the best case, the key might be present at the first index. So the best
case complexity is O(1)
ASSI.PRO.UPEKSHA CHAUDHRI 4
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
• Worst Case: In the worst case, the key might be present at the last index i.e.,
opposite to the end from which the search has started in the list. So the worst-case
complexity is O(N) where N is the size of the list.
• Average Case: O(N)
Auxiliary Space: O(1) as except for the variable to iterate through the list, no other variable
is used.
Applications of Linear Search Algorithm:
• Unsorted Lists: When we have an unsorted array or list, linear search is most
commonly used to find any element in the collection.
• Small Data Sets: Linear Search is preferred over binary search when we have small
data sets with
• Searching Linked Lists: In linked list implementations, linear search is commonly used
to find elements within the list. Each node is checked sequentially until the desired
element is found.
• Simple Implementation: Linear Search is much easier to understand and implement
as compared to Binary Search or Ternary Search.
Advantages of Linear Search Algorithm:
• Linear search can be used irrespective of whether the array is sorted or not. It can be
used on arrays of any data type.
• Does not require any additional memory.
• It is a well-suited algorithm for small datasets.
Disadvantages of Linear Search Algorithm:
• Linear search has a time complexity of O(N), which in turn makes it slow for large
datasets.
• Not suitable for large arrays.
Binary Search:-
Binary Search Algorithm is a searching algorithm used in a sorted array by repeatedly
dividing the search interval in half. The idea of binary search is to use the information that
the array is sorted and reduce the time complexity to O(log N).
ASSI.PRO.UPEKSHA CHAUDHRI 5
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Binary search is a search algorithm used to find the position of a target value within
a sorted array. It works by repeatedly dividing the search interval in half until the target
value is found or the interval is empty. The search interval is halved by comparing the target
element with the middle value of the search space.
Binary Search Algorithm
Below is the step-by-step algorithm for Binary Search:
• Divide the search space into two halves by finding the middle index “mid”.
• Compare the middle element of the search space with the key.
• If the key is found at middle element, the process is terminated.
• If the key is not found at middle element, choose which half will be used as the next
search space.
o If the key is smaller than the middle element, then the left side is used for
next search.
o If the key is larger than the middle element, then the right side is used for
next search.
• This process is continued until the key is found or the total search space is exhausted.
1.
ASSI.PRO.UPEKSHA CHAUDHRI 6
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
2.
3.
4.
ASSI.PRO.UPEKSHA CHAUDHRI 7
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
• Time Complexity:
o Best Case: O(1)
o Average Case: O(log N)
o Worst Case: O(log N)
• Auxiliary Space: O(1), If the recursive call stack is considered then the auxiliary space
will be O(logN).
Applications of Binary Search Algorithm
• Binary search can be used as a building block for more complex algorithms used in
machine learning, such as algorithms for training neural networks or finding the
optimal hyperparameters for a model.
• It can be used for searching in computer graphics such as algorithms for ray tracing
or texture mapping.
• It can be used for searching a database.
Advantages of Binary Search
• Binary search is faster than linear search, especially for large arrays.
• More efficient than other searching algorithms with a similar time complexity, such
as interpolation search or exponential search.
• Binary search is well-suited for searching large datasets that are stored in external
memory, such as on a hard drive or in the cloud.
Disadvantages of Binary Search
• The array should be sorted.
• Binary search requires that the data structure being searched be stored in contiguous
memory locations.
• Binary search requires that the elements of the array be comparable, meaning that
they must be able to be ordered.
Example:- binary search
#include <stdio.h>
int main() {
ASSI.PRO.UPEKSHA CHAUDHRI 8
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
first = 0;
last = n - 1;
middle = (first + last) / 2;
ASSI.PRO.UPEKSHA CHAUDHRI 9
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
return 0;
}
Second Pass:
Place the second largest element at correct position
ASSI.PRO.UPEKSHA CHAUDHRI 10
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Third Pass:
Place the remaining two elements at their correct positions.
ASSI.PRO.UPEKSHA CHAUDHRI 11
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
void main() {
int array[100], n, i, j, temp;
ASSI.PRO.UPEKSHA CHAUDHRI 12
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
ASSI.PRO.UPEKSHA CHAUDHRI 13
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
#include <stdio.h>
#include <stdlib.h>
ASSI.PRO.UPEKSHA CHAUDHRI 14
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
int i = low - 1;
for (int j = low; j <= high - 1; 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) {
ASSI.PRO.UPEKSHA CHAUDHRI 15
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
int main() {
int arr[] = {10, 7, 8, 9, 1, 5};
int n = sizeof(arr) / sizeof(arr[0]);
quickSort(arr, 0, n - 1);
printf("Sorted Array\n");
printArray(arr, n);
return 0;
}
Time Complexity:
• Best Case : Ω (N log (N))
The best-case scenario for quicksort occur when the pivot chosen at the each step
divides the array into roughly equal halves.
In this case, the algorithm will make balanced partitions, leading to efficient Sorting.
• Average Case: θ ( N log (N))
Quicksort’s average-case performance is usually very good in practice, making it one
of the fastest sorting Algorithm.
• Worst Case: O(N ^ 2)
The worst-case Scenario for Quicksort occur when the pivot at each step consistently
results in highly unbalanced partitions. When the array is already sorted and the
pivot is always chosen as the smallest or largest element. To mitigate the worst-case
Scenario, various techniques are used such as choosing a good pivot (e.g., median of
ASSI.PRO.UPEKSHA CHAUDHRI 16
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
ASSI.PRO.UPEKSHA CHAUDHRI 17
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
• For the first position in the sorted array, the whole array is traversed from index 0 to
4 sequentially. The first position where 64 is stored presently, after traversing whole
array it is clear that 11 is the lowest value.
• Thus, replace 64 with 11. After one iteration 11, which happens to be the least value
in the array, tends to appear in the first position of the sorted list.
Second Pass:
• For the second position, where 25 is present, again traverse the rest of the array in a
sequential manner.
• After traversing, we found that 12 is the second lowest value in the array and it
should appear at the second place in the array, thus swap these values.
Third Pass:
• Now, for third place, where 25 is present again traverse the rest of the array and find
the third least value present in the array.
• While traversing, 22 came out to be the third least value and it should appear at the
third place in the array, thus swap 22 with element present at third position.
ASSI.PRO.UPEKSHA CHAUDHRI 18
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Fourth pass:
• Similarly, for fourth position traverse the rest of the array and find the fourth least
element in the array
• As 25 is the 4th lowest value hence, it will place at the fourth position.
Fifth Pass:
• At last the largest value present in the array automatically get placed at the last
position in the array
• The resulted array is the sorted array.
ASSI.PRO.UPEKSHA CHAUDHRI 19
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Example:-
#include <stdio.h>
void main() {
int arr[5] = {64, 25, 12, 22, 11};
int n = 5;
int i, j, minIndex, temp;
ASSI.PRO.UPEKSHA CHAUDHRI 20
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
arr[minIndex] = arr[i];
arr[i] = temp;
}
ASSI.PRO.UPEKSHA CHAUDHRI 21
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Heap Sort:-
Heap sort is a comparison-based sorting technique based on Binary Heap Data Structure. It
can be seen as an optimization over selection sort where we first find the max (or min)
element and swap it with the last (or first). We repeat the same process for the remaining
elements. In Heap Sort, we use Binary Heap so that we can quickly find and move the max
element (In O(Log n) instead of O(n)) and hence achieve the O(n Log n) time complexity.
Heap Sort Algorithm
First convert the array into a max heap using heapify, Then one by one delete the root node
of the Max-heap and replace it with the last node and heapify. Repeat this process while size
of heap is greater than 1.
• Build a max heap from the given input array.
• Repeat the following steps until the heap contains only one element:
o Swap the root element of the heap (which is the largest element) with the
last element of the heap.
o Remove the last element of the heap (which is now in the correct position).
o Heapify the remaining elements of the heap.
• The sorted array is obtained by reversing the order of the elements in the input array.
ASSI.PRO.UPEKSHA CHAUDHRI 22
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Perform heap sort: Remove the maximum element in each step (i.e., move it to the end
position and remove that) and then consider the remaining elements and transform it into a
max heap.
• Delete the root element (10) from the max heap. In order to delete this node, try to
swap it with the last node, i.e. (1). After removing the root element, again heapify it
to convert it into max heap.
ASSI.PRO.UPEKSHA CHAUDHRI 23
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
• Now when the root is removed once again it is sorted. and the sorted array will be
like arr[] = {1, 3, 4, 5, 10} .
ASSI.PRO.UPEKSHA CHAUDHRI 24
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
// Heap Sort in C
#include <stdio.h>
ASSI.PRO.UPEKSHA CHAUDHRI 25
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
int left = 2 * i + 1;
int right = 2 * i + 2;
largest = left;
largest = right;
if (largest != i) {
swap(&arr[i], &arr[largest]);
ASSI.PRO.UPEKSHA CHAUDHRI 26
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
heapify(arr, N, i);
// Heap sort
for (int i = N - 1; i >= 0; i--) {
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
int main()
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int N = sizeof(arr) / sizeof(arr[0]);
heapSort(arr, N);
printf("Sorted array is\n");
printArray(arr, N);
}
ASSI.PRO.UPEKSHA CHAUDHRI 27
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
ASSI.PRO.UPEKSHA CHAUDHRI 28
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
• We start with second element of the array as first element in the array is assumed to
be sorted.
• Compare second element with the first element and check if the second element is
smaller then swap them.
• Move to the third element and compare it with the second element, then the first
element and swap as necessary to put it in the correct position among the first three
elements.
• Continue this process, comparing each element with the ones before it and swapping
as needed to place it in the correct position among the sorted elements.
• Repeat until the entire array is sorted.
Working of Insertion Sort Algorithm:
Consider an array having elements : {23, 1, 10, 5, 2}
Initial:
• Current element is 23
• The first element in the array is assumed to be sorted.
• The sorted part until 0th index is : [23]
First Pass:
• Compare 1 with 23 (current element with the sorted part).
• Since 1 is smaller, insert 1 before 23 .
ASSI.PRO.UPEKSHA CHAUDHRI 29
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
#include <stdio.h>
void main() {
int n, i, j, temp;
int arr[100]; // Adjust size as needed
ASSI.PRO.UPEKSHA CHAUDHRI 30
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Shell Sort:-
Shell sort is mainly a variation of Insertion Sort. In insertion sort, we move elements only
one position ahead. When an element has to be moved far ahead, many movements are
involved. The idea of ShellSort is to allow the exchange of far items. In Shell sort, we make
the array h-sorted for a large value of h. We keep reducing the value of h until it becomes 1.
An array is said to be h-sorted if all sublists of every h’th element are sorted.
Algorithm:
ASSI.PRO.UPEKSHA CHAUDHRI 31
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Step 1 − Start
Step 2 − Initialize the value of gap size, say h.
Step 3 − Divide the list into smaller sub-part. Each must have equal intervals to h.
Step 4 − Sort these sub-lists using insertion sort.
Step 5 – Repeat this step 2 until the list is sorted.
Step 6 – Print a sorted list.
Step 7 – Stop.
// C++ implementation of Shell Sort
#include <iostream>
using namespace std;
int j;
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
arr[j] = arr[j - gap];
ASSI.PRO.UPEKSHA CHAUDHRI 32
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
int main()
{
int arr[] = {12, 34, 54, 2, 3}, i;
int n = sizeof(arr)/sizeof(arr[0]);
shellSort(arr, n);
return 0;
}
Output
Array before sorting:
12 34 54 2 3
Array after sorting:
2 3 12 34 54
ASSI.PRO.UPEKSHA CHAUDHRI 33
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Time Complexity: Time complexity of the above implementation of Shell sort is O(n2). In the
above implementation, the gap is reduced by half in every iteration. There are many other
ways to reduce gaps which leads to better time complexity. See this for more details.
Worst Case Complexity
The worst-case complexity for shell sort is O(n2)
Best Case Complexity
When the given array list is already sorted the total count of comparisons of each interval is
equal to the size of the given array.
So best case complexity is Ω(n log(n))
Average Case Complexity
The Average Case Complexity: O(n*log n)~O(n1.25)
Space Complexity
The space complexity of the shell sort is O(1).
ASSI.PRO.UPEKSHA CHAUDHRI 34
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
3. Merge: The sorted subarrays are merged back together in sorted order. The process
continues until all elements from both subarrays have been merged.
Illustration of Merge Sort:
Let’s sort the array or list [38, 27, 43, 10] using Merge Sort
ASSI.PRO.UPEKSHA CHAUDHRI 35
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
ASSI.PRO.UPEKSHA CHAUDHRI 37
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
}
k++;
}
ASSI.PRO.UPEKSHA CHAUDHRI 38
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
}
// Driver code
int main()
{
int arr[] = { 12, 11, 13, 5, 6, 7 };
int arr_size = sizeof(arr) / sizeof(arr[0]);
ASSI.PRO.UPEKSHA CHAUDHRI 39
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
return 0;
}
Output:-
Given array is
12 11 13 5 6 7
Sorted array is
5 6 7 11 12 13
Complexity Analysis of Merge Sort:
• Time Complexity:
o Best Case: O(n log n), When the array is already sorted or nearly sorted.
o Average Case: O(n log n), When the array is randomly ordered.
o Worst Case: O(n log n), When the array is sorted in reverse order.
• Auxiliary Space: O(n), Additional space is required for the temporary array used
during merging.
Applications of Merge Sort:
• Sorting large datasets
• External sorting (when the dataset is too large to fit in memory)
• Inversion counting
• Merge Sort and its variations are used in library methods of programming languages.
For example its variation TimSort is used in Python, Java Android and Swift. The main
reason why it is preferred to sort non-primitive types is stability which is not there in
QuickSort. For example Arrays.sort in Java uses QuickSort while Collections.sort uses
MergeSort.
• It is a preferred algorithm for sorting Linked lists.
• It can be easily parallelized as we can independently sort subarrays and then merge.
• The merge function of merge sort to efficiently solve the problems like union and
intersection of two sorted arrays.
Advantages of Merge Sort:
• Stability : Merge sort is a stable sorting algorithm, which means it maintains the
relative order of equal elements in the input array.
ASSI.PRO.UPEKSHA CHAUDHRI 40
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Radix Sort:-
Radix Sort is a linear sorting algorithm that sorts elements by processing them digit by digit.
It is an efficient sorting algorithm for integers or strings with fixed-size keys.
Radix Sort Algorithm
The key idea behind Radix Sort is to exploit the concept of place value. It assumes that
sorting numbers digit by digit will eventually result in a fully sorted list. Radix Sort can be
performed using different variations, such as Least Significant Digit (LSD) Radix Sort or Most
Significant Digit (MSD) Radix Sort.
To perform radix sort on the array [170, 45, 75, 90, 802, 24, 2, 66], we follow these steps:
Step 1: Find the largest element in the array, which is 802. It has three digits, so we will
iterate three times, once for each significant place.
ASSI.PRO.UPEKSHA CHAUDHRI 41
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
Step 2: Sort the elements based on the unit place digits (X=0). We use a stable sorting
technique, such as counting sort, to sort the digits at each significant place. It’s important to
understand that the default implementation of counting sort is unstable i.e. same keys can
be in a different order than the input array. To solve this problem, We can iterate the input
array in reverse order to build the output array. This strategy helps us to keep the same keys
in the same order as they appear in the input array.
Sorting based on the unit place:
• Perform counting sort on the array based on the unit place digits.
• The sorted array based on the unit place is [170, 90, 802, 2, 24, 45, 75, 66].
• Perform counting sort on the array based on the hundreds place digits.
• The sorted array based on the hundreds place is [2, 24, 45, 66, 75, 90, 170, 802].
ASSI.PRO.UPEKSHA CHAUDHRI 44
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
// Driver code
int main() {
int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};
int n = sizeof(arr) / sizeof(arr[0]);
// Function call
ASSI.PRO.UPEKSHA CHAUDHRI 45
BZ GROW MORE INSTITUTE OF MSC(CA&IT)
radixSort(arr, n);
printArray(arr, n);
return 0;
}
Time Complexity:
• Radix sort is a non-comparative integer sorting algorithm that sorts data with integer
keys by grouping the keys by the individual digits which share the same significant
position and value. It has a time complexity of O(d * (n + b)), where d is the number
of digits, n is the number of elements, and b is the base of the number system being
used.
• In practical implementations, radix sort is often faster than other comparison-based
sorting algorithms, such as quicksort or merge sort, for large datasets, especially
when the keys have many digits. However, its time complexity grows linearly with the
number of digits, and so it is not as efficient for small datasets.
ASSI.PRO.UPEKSHA CHAUDHRI 46