0% found this document useful (0 votes)
14 views41 pages

CDS Unit 5

The document discusses the Linear Search Algorithm, which is a simple method for finding an element in an unordered list by sequentially checking each element. It outlines the algorithm's steps, time complexity (O(n) in the worst case), and provides a C language implementation. Additionally, it briefly compares Linear Search with Binary Search and Bubble Sort, highlighting their respective complexities and use cases.

Uploaded by

gammersadda3
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)
14 views41 pages

CDS Unit 5

The document discusses the Linear Search Algorithm, which is a simple method for finding an element in an unordered list by sequentially checking each element. It outlines the algorithm's steps, time complexity (O(n) in the worst case), and provides a C language implementation. Additionally, it briefly compares Linear Search with Binary Search and Bubble Sort, highlighting their respective complexities and use cases.

Uploaded by

gammersadda3
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/ 41

UNIT- 5

Linear Search Algorithm

Searching is the process of finding some particular element in the list. If the element is present in the list,
then the process is called successful, and the process returns the location of that element; otherwise, the
search is called unsuccessful.

Two popular search methods are Linear Search and Binary Search. So, here we will discuss the popular
searching technique, i.e., Linear Search Algorithm.

Linear search is also called as sequential search algorithm. It is the simplest searching algorithm. In Linear
search, we simply traverse the list completely and match each element of the list with the item whose location
is to be found. If the match is found, then the location of the item is returned; otherwise, the algorithm returns
NULL.

It is widely used to search an element from the unordered list, i.e., the list in which items are not sorted. The
worst-case time complexity of linear search is O(n).

The steps used in the implementation of Linear Search are listed as follows -

o First, we have to traverse the array elements using a for loop.


o In each iteration of for loop, compare the search element with the current array element, and -

o If the element matches, then return the index of the corresponding array element.
o If the element does not match, then move to the next element.
o If there is no match or the search element is not present in the given array, return -1.

Now, let's see the algorithm of linear search.

Algorithm
Linear_Search(a, n, val) // 'a' is the given array, 'n' is the size of given array, 'val' is the value
to search Step 1: set pos = -1
Step 2: set i = 1
Step 3: repeat step 4
while i <= n Step 4: if
a[i] == val
Set pos = i print pos go to step 6
[end of if]
Set i = i
+ 1 [end
of loop]
Step 5: if pos = -1
print "value is not present in the array
" [end of if]
Step 6: exit
Working of Linear search:

Now, let's see the working of the linear search Algorithm.

To understand the working of linear search algorithm, let's take an unsorted array. It will be easy to
understand the working of linear search with an example.

Let the elements of array are -

Let the element to be searched is K = 41

Now, start from the first element and compare K with each element of the array.

The value of K, i.e., 41, is not matched with the first element of the array. So, move to the next element. And
follow the same process until the respective element is found.
Now, the element to be searched is found. So algorithm will return the index of the element matched.

Linear Search complexity

Now, let's see the time complexity of linear search in the best case, average case, and worst case. We will
also see the space complexity of linear search.

1. Time Complexity

Case Time Complexity

Best Case O(1)

Average Case O(n)

Worst Case O(n)

o Best Case Complexity - In Linear search, best case occurs when the element we are finding is at the first
position of the array. The best-case time complexity of linear search is O(1).
o Average Case Complexity - The average case time complexity of linear search is O(n).
o Worst Case Complexity - In Linear search, the worst case occurs when the element we are looking is
present at the end of the array. The worst-case in linear search could be when the target element is not present
in the given array, and we have to traverse the entire array. The worst-case time complexity of linear search is
O(n).

The time complexity of linear search is O(n) because every element in the array is compared only once.

2. Space Complexity
Space Complexity O(1)

o The space complexity of linear search is O(1).

Implementation of Linear Search

Now, let's see the programs of linear search in different programming languages.

Program: Write a program to implement linear search in C language.

1. #include <stdio.h>
2. int linearSearch(int a[], int n, int val) {
3. // Going through array sequencially
4. for (int i = 0; i < n; i++)
5. {
6. if (a[i] == val)
7. return i+1;
8. }
9. return -1;
10. }
11. int main() {

12. int a[] = {70, 40, 30, 11, 57, 41, 25, 14, 52}; // given array
13. int val = 41; // value to be searched
14. int n = sizeof(a) / sizeof(a[0]); // size of array
15. int res = linearSearch(a, n, val); // Store result
16. printf("The elements of the array are - ");
17. for (int i = 0; i < n; i++)
18. printf("%d ", a[i]);
19. printf("\nElement to be searched is - %d", val);
20. if (res == -1)
21. printf("\nElement is not present in the array");
22. else
23. printf("\nElement is present at %d position of array", res);
24. return 0;
25. }

Output

Binary Search Algorithm:

Linear Search and Binary Search are the two popular searching techniques. Here we will discuss the Binary
Search Algorithm.

Binary search is the search technique that works efficiently on sorted lists. Hence, to search an element into
some list using the binary search technique, we must ensure that the list is sorted.

Binary search follows the divide and conquer approach in which the list is divided into two halves, and the
item is compared with the middle element of the list. If the match is found then, the location of the middle
element is returned. Otherwise, we search into either of the halves depending upon the result produced
through the match.

NOTE: Binary search can be implemented on sorted array elements. If the list elements are not
arranged in a sorted manner, we have first to sort them.

Now, let's see the algorithm of Binary Search.

Algorithm
1. Binary_Search(a, lower_bound, upper_bound, val) // 'a' is the given array, 'lower_bound' is the
index of the fi rst array element, 'upper_bound' is the index of the last array element, 'val' is the value to
search
2. Step 1: set low= lower_bound, high = upper_bound, pos = - 1
3. Step 2: repeat steps 3 and 4 while beg <=end

4. Step 3: set mid = (low+ high)/2


5. Step 4: if a[mid] = val
6. set pos = mid
7. print pos
8. go to step 6
9. else if a[mid] > val
10. set high = mid - 1
11. else
12. set low = mid + 1
13. [end of if]
14. [end of loop]
15. Step 5: if pos = -1
16. print "value is not present in the array"
17. [end of if]
18. Step 6: exit
Working of Binary search

Now, let's see the working of the Binary Search Algorithm.

To understand the working of the Binary search algorithm, let's take a sorted array. It will be easy to understand
the working of Binary search with an example.

Let the elements of array are -

Let the element to search is, K = 56

We have to use the below formula to calculate the mid of the array -

1. mid = (low + high)/2

So, in the given array -

low = 0

high = 8

mid = (0 + 8)/2 = 4. So, 4 is the mid of the array.


Now, the element to search is found. So algorithm will return the index of the element matched.

Binary Search complexity

Now, let's see the time complexity of Binary search in the best case, average case, and worst case. We will
also see the space complexity of Binary search.

1. Time Complexity

Case Time Complexity

Best Case O(1)

Average Case O(logn)

Worst Case O(logn)

o Best Case Complexity - In Binary search, best case occurs when the element to search is found in first
comparison, i.e., when the first middle element itself is the element to be searched. The best-case time
complexity of Binary search is O(1).
o Average Case Complexity - The average case time complexity of Binary search is O(logn).
o Worst Case Complexity - In Binary search, the worst case occurs, when we have to keep reducing the
search space till it has only one element. The worst-case time complexity of Binary search is O(logn).

2. Space Complexity
Space Complexity O(1)

o The space complexity of binary search is O(1).

Implementation of Binary Search:

Now, let's see the programs of Binary search in different programming languages.

Program: Write a program to implement Binary search in C language.


1. #include <stdio.h>
2. int binarySearch(int a[], int low, int high, int
val)
3. {
4. int mid;
5. if(high>= low)
6. { mid = (low + high)/2;
7. /* if the item to be searched is present at middle */
8. if(a[mid] == val)
9. {
10. return mid+1;
11. }
12. /* if the item to be searched is smaller than middle, then it can only be in left subarray */
13. else if(a[mid] < val)
14. {
15. return binarySearch(a, mid+1, high, val);
16. }
17. /* if the item to be searched is greater than middle, then it can only be in right subarray */
18. else
19. {
20. return binarySearch(a, low, mid-1, val);
21. }
22. }

23. return -1;


24. }
25. int main() {
26. int a[] = {11, 14, 25, 30, 40, 41, 52, 57, 70}; // given array
27. int val = 40; // value to be searched
28. int n = sizeof(a) / sizeof(a[0]); // size of array
29. int res = binarySearch(a, 0, n-1, val); // Store result
30. printf("The elements of the array are - ");
31. for (int i = 0; i < n; i++)
32. printf("%d ", a[i]);
33. printf("\nElement to be searched is - %d", val);
34. if (res == -1)
35. printf("\nElement is not present in the array");
36. else
37. printf("\nElement is present at %d position of array", res);
38. return 0;
39. }
Output

Bubble sort Algorithm

Bubble sort works on the repeatedly swapping of adjacent elements until they are not in the intended order. It
is called bubble sort because the movement of array elements is just like the movement of air bubbles in the
water. Bubbles in water rise up to the surface; similarly, the array elements in bubble sort move to the end in
each iteration.

Although it is simple to use, it is primarily used as an educational tool because the performance of bubble sort
is poor in the real world. It is not suitable for large data sets. The average and worst-case complexity of
Bubble sort is O(n2), where n is a number of items.

Bubble short is majorly used where -

o complexity does not matter


o simple and shortcode is preferred

Algorithm

In the algorithm given below, suppose arr is an array of n elements. The assumed swap function in the
algorithm will swap the values of given array elements.

1. begin BubbleSort(arr)
2. for all array elements
3. if arr[i] > arr[i+1]
4. swap(arr[i], arr[i+1])
5. end if
6. end for
7. return arr
8. end BubbleSort
Working of Bubble sort Algorithm

Now, let's see the working of Bubble sort Algorithm.

To understand the working of bubble sort algorithm, let's take an unsorted array. We are taking a short and
accurate array, as we know the complexity of bubble sort is O(n2).

Let the elements of array are -

First Pass
Sorting will start from the initial two elements. Let compare them to check which is greater.

Here, 32 is greater than 13 (32 > 13), so it is already sorted. Now, compare 32 with 26.

Here, 26 is smaller than 36. So, swapping is required. After swapping new array will look like -

Now, compare 32 and 35.

Here, 35 is greater than 32. So, there is no swapping required as they are already sorted.

Now, the comparison will be in between 35 and 10.

Here, 10 is smaller than 35 that are not sorted. So, swapping is required. Now, we reach at the end of the array.
After first pass, the array will be -

Now, move to the second iteration.

Second Pass

The same process will be followed for second iteration.


Here, 10 is smaller than 32. So, swapping is required. After swapping, the array will be -

Now, move to the third iteration.

Third Pass

The same process will be followed for third iteration.

Here, 10 is smaller than 26. So, swapping is required. After swapping, the array will be –

Now, move to the fourth iteration.

Fourth pass

Similarly, after the fourth iteration, the array will be -

Hence, there is no swapping required, so the array is completely sorted.

Bubble sort complexity

Now, let's see the time complexity of bubble sort in the best case, average case, and worst case. We will also

see the space complexity of bubble sort.

1. Time Complexity
Case Time Complexity

Best Case O(n)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is already sorted. The
best- case time complexity of bubble sort is O(n).
o Average Case Complexity - It occurs when the array elements are in jumbled order that is not properly
ascending and not properly descending. The average case time complexity of bubble sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to be sorted in reverse order.
That means suppose you have to sort the array elements in ascending order, but its elements are in descending
order. The worst-case time complexity of bubble sort is O(n2).

2. Space Complexity
Space Complexity O(1)

Stable YES

o The space complexity of bubble sort is O(1). It is because, in bubble sort, an extra variable is required
for swapping.
o The space complexity of optimized bubble sort is O(2). It is because two extra variables are required in
optimized bubble sort.

Now, let's discuss the optimized bubble sort algorithm.

Optimized Bubble sort Algorithm:

In the bubble sort algorithm, comparisons are made even when the array is already sorted. Because of that,
the execution time increases.

To solve it, we can use an extra variable swapped. It is set to true if swapping requires; otherwise, it is set to
false.

It will be helpful, as suppose after an iteration, if there is no swapping required, the value of variable
swapped will be false. It means that the elements are already sorted, and no further iterations are required.

This method will reduce the execution time and also optimizes the bubble sort.

Algorithm for optimized bubble sort


The basic bubble sort algorithm can be explained as follows:
1. bubbleSort(array)

2. for i <- 1 to indexOfLastUnsortedElement-1

3. if leftElement > rightElement

4. swap leftElement and rightElement

5. end bubbleSort

Implementation of Bubble sort

Now, let's see the programs of Bubble sort in different programming languages.

Program: Write a program to implement bubble sort in C language.

1. #include<stdio.h>
2. void print(int a[], int n) //function to print array
elements 3. {
4. int i;
5. for(i = 0; i < n; i++)
6. {
7. printf("%d ",a[i]);
8. }
9. }
10. void bubble(int a[], int n) // function to implement bubble sort
11. {
12.int i, j, temp;
13.for(i = 0; i < n; i++)
14. {
15. for(j = i+1; j < n; j++)
16. {
17. if(a[j] < a[i])
18. {
19. temp = a[i];
20. a[i] = a[j];
21. a[j] = temp;
22. }
23. }
24. }
25. }
26. void main ()
27. {
28. int i, j,temp;
29. int a[5] = { 10, 35, 32, 13, 26};
30. int n = sizeof(a)/sizeof(a[0]);
31. printf("Before sorting array elements are - \n");
32. print(a, n);

33. bubble(a, n);


34. printf("\nAfter sorting array elements are - \n");
35. print(a, n);
36. }

Output

Selection Sort Algorithm

In selection sort, the smallest value among the unsorted elements of the array is selected in every pass and
inserted to its appropriate position into the array. It is also the simplest algorithm. It is an in-place comparison
sorting algorithm. In this algorithm, the array is divided into two parts, first is sorted part, and another one is
the unsorted part. Initially, the sorted part of the array is empty, and unsorted part is the given array. Sorted
part is placed at the left, while the unsorted part is placed at the right.

In selection sort, the first smallest element is selected from the unsorted array and placed at the first position.
After that second smallest element is selected and placed in the second position. The process continues until
the array is entirely sorted.

The average and worst-case complexity of selection sort is O(n2), where n is the number of items. Due to
this, it is not suitable for large data sets.

Selection sort is generally used when -

o A small array is to be sorted


o Swapping cost doesn't matter
o It is compulsory to check all elements

Now, let's see the algorithm of selection sort.

Algorithm
1. SELECTION SORT(arr, n)
2. Step 1: Repeat Steps 2 and 3 for i = 0 to n-1
3. Step 2: CALL SMALLEST(arr, i, n, pos)
4. Step 3: SWAP arr[i] with arr[pos]
5. [END OF LOOP]
6. Step 4: EXIT
7. SMALLEST (arr, i, n, pos)
8. Step 1: [INITIALIZE] SET SMALL = arr[i]
9. Step 2: [INITIALIZE] SET pos = i
10. Step 3: Repeat for j = i+1 to n
11. if (SMALL > arr[j])
SET SMALL = arr[j]
12. SET pos = j
13. [END OF if]
14. [END OF LOOP]
15. Step 4: RETURN pos
Working of Selection sort Algorithm

Now, let's see the working of the Selection sort Algorithm.

To understand the working of the Selection sort algorithm, let's take an unsorted array. It will be easier to
understand the Selection sort via an example.

Let the elements of array are -

Now, for the first position in the sorted array, the entire array is to be scanned sequentially.

At present, 12 is stored at the first position, after searching the entire array, it is found that 8 is the smallest
value.

So, swap 12 with 8. After the first iteration, 8 will appear at the first position in the sorted array.

For the second position, where 29 is stored presently, we again sequentially scan the rest of the items of
unsorted array. After scanning, we find that 12 is the second lowest element in the array that should be
appeared at second position.

Now, swap 29 with 12. After the second iteration, 12 will appear at the second position in the sorted array.
So, after two iterations, the two smallest values are placed at the beginning in a sorted way.

The same process is applied to the rest of the array elements. Now, we are showing a pictorial representation of
the entire sorting process.

Now, the array is completely sorted.

Selection sort complexity

Now, let's see the time complexity of selection sort in best case, average case, and in worst case. We will
also see the space complexity of the selection sort.

• Time Complexity
Case Time Complexity

Best Case O(n2)

Average O(n2)
Case
Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is already sorted. The
best-case time complexity of selection sort is O(n2).

o Average Case Complexity - It occurs when the array elements are in jumbled order that is not properly
ascending and not properly descending. The average case time complexity of selection sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to be sorted in reverse order. That
means suppose you have to sort the array elements in ascending order, but its elements are in descending
order. The worst-case time complexity of selection sort is O(n2).

• Space Complexity
Space Complexity O(1)

Stable YES

o The space complexity of selection sort is O(1). It is because, in selection sort, an extra variable is
required for swapping.

Implementation of selection sort

Now, let's see the programs of selection sort in different programming languages.

Program: Write a program to implement selection sort in C language.

1. #include
<stdio.h> 2.
3. void selection(int arr[], int
n) 4. {
5. int i, j,
small; 6.
7. for (i = 0; i < n-1; i++) // One by one move boundary of unsorted subarray
8. {
9. small = i; //minimum element in unsorted array
10.
11. for (j = i+1; j < n; j++)
12. if (arr[j] < arr[small])
13. small = j;
14. // Swap the minimum element with the first element
15. int temp = arr[small];
16. arr[small] = arr[i];
17. arr[i] = temp;
18. }
19. }
20.
21. void printArr(int a[], int n) /* function to print the array */
22. {
23. int i;
24. for (i = 0; i < n; i++)
25. printf("%d ", a[i]);
26. }
27.
28. int main()
29. {
30. int a[] = { 12, 31, 25, 8, 32, 17 };
31. int n = sizeof(a) / sizeof(a[0]);
32. printf("Before sorting array elements are - \n");
33. printArr(a, n);
34. selection(a, n);
35. printf("\nAfter sorting array elements are - \n");
36. printArr(a, n);
37. return 0;
38. }
Output:

After the execution of above code, the output will be -

Insertion Sort Algorithm

Insertion sort works similar to the sorting of playing cards in hands. It is assumed that the first card is already
sorted in the card game, and then we select an unsorted card. If the selected unsorted card is greater than the
first card, it will be placed at the right side; otherwise, it will be placed at the left side. Similarly, all unsorted
cards are taken and put in their exact place.

The same approach is applied in insertion sort. The idea behind the insertion sort is that first take one
element, iterate it through the sorted array. Although it is simple to use, it is not appropriate for large data sets
as the time complexity of insertion sort in the average case and worst case is O(n2), where n is the number of
items. Insertion sort is less efficient than the other sorting algorithms like heap sort, quick sort, merge sort,
etc.

Insertion sort has various advantages such as -

o Simple implementation
o Efficient for small data sets
o Adaptive, i.e., it is appropriate for data sets that are already substantially sorted.

Now, let's see the algorithm of insertion sort.

Algorithm

The simple steps of achieving the insertion sort are listed as follows -

Step 1 - If the element is the first element, assume that it is already sorted. Return 1.

Step2 - Pick the next element, and store it separately in a key. Step3 - Now,

compare the key with all elements in the sorted array.


Step 4 - If the element in the sorted array is smaller than the current element, then move to the next element.
Else, shift greater elements in the array towards the right.

Step 5 - Insert the value.

Step 6 - Repeat until the array is sorted.

Working of Insertion sort Algorithm

Now, let's see the working of the insertion sort Algorithm.

To understand the working of the insertion sort algorithm, let's take an unsorted array. It will be easier to
understand the insertion sort via an example.

Let the elements of array are -

Initially, the first two elements are compared in insertion sort.

Here, 31 is greater than 12. That means both elements are already in ascending order. So, for now, 12 is
stored in a sorted sub-array.

Now, move to the next two elements and compare them.

Here, 25 is smaller than 31. So, 31 is not at correct position. Now, swap 31 with 25. Along with swapping,
insertion sort will also check it with all elements in the sorted array.

For now, the sorted array has only one element, i.e. 12. So, 25 is greater than 12. Hence, the sorted array remains
sorted after swapping.

Now, two elements in the sorted array are 12 and 25. Move forward to the next elements that are 31 and 8.
Both 31 and 8 are not sorted. So, swap them.

After swapping, elements 25 and 8 are unsorted.

So, swap them.

Now, elements 12 and 8 are unsorted.

So, swap them too.

Now, the sorted array has three items that are 8, 12 and 25. Move to the next items that are 31 and 32.

Hence, they are already sorted. Now, the sorted array includes 8, 12, 25 and 31.

Move to the next elements that are 32 and 17.

Pause

Unmut
e

17 is smaller than 32. So, swap them.

Swapping makes 31 and 17 unsorted. So, swap them too.


Now, swapping makes 25 and 17 unsorted. So, perform swapping again.

Now, the array is completely sorted.

Insertion sort complexity

Now, let's see the time complexity of insertion sort in best case, average case, and in worst case. We will also
see the space complexity of insertion sort.

1. Time Complexity
Case Time Complexity

Best Case O(n)

Average Case O(n2)

Worst Case O(n2)

o Best Case Complexity - It occurs when there is no sorting required, i.e. the array is already sorted.
The best-case time complexity of insertion sort is O(n).
o Average Case Complexity - It occurs when the array elements are in jumbled order that is not
properly ascending and not properly descending. The average case time complexity of insertion sort is O(n2).
o Worst Case Complexity - It occurs when the array elements are required to be sorted in reverse
order. That means suppose you have to sort the array elements in ascending order, but its elements are in
descending order. The worst-case time complexity of insertion sort is O(n2).

2. Space Complexity
Space Complexity O(1)

Stable YES

o The space complexity of insertion sort is O(1). It is because, in insertion sort, an extra variable is
required for swapping.

Implementation of insertion sort

Now, let's see the programs of insertion sort in different programming languages.

Program: Write a program to implement insertion sort in C language.


1. #include
<stdio.h> 2.
3. void insert(int a[], int n) /* function to sort an aay with insertion sort
*/ 4. {
5. int i, j, temp;
6. for (i = 1; i < n; i++) {
7. temp = a[i];
8. j = i - 1;
9.
10. while(j>=0 && temp <= a[j]) /* Move the elements greater than temp to one position ahead from
th eir current position*/

11. {
12. a[j+1] = a[j];
13. j = j-1;
14. }
15. a[j+1] = temp;
16. }
17. }
18.
19. void printArr(int a[], int n) /* function to print the array */
20. {
21. int i;
22. for (i = 0; i < n; i++)
23. printf("%d ", a[i]);
24. }
25.
26. int main()
27. {
28. int a[] = { 12, 31, 25, 8, 32, 17 };
29. int n = sizeof(a) / sizeof(a[0]);
30. printf("Before sorting array elements are - \n");
31. printArr(a, n);
32. insert(a, n);
33. printf("\nAfter sorting array elements are - \n");
34. printArr(a, n);
35.
36. return 0;
37. }

Output:
Program: Write a program to implement insertion sort in python.

1. def insertionSort(a): # Function to implement insertion sort


2. for i in range(1, len(a)):
3. temp = a[i]

4. # Move the elements greater than temp to one position


5. #ahead from their current position
6. j = i-1
7. while j >= 0 and temp < a[j] :
8. a[j + 1] = a[j]
9. j = j-1
10. a[j + 1] = temp
11.
12. def printArr(a): # function to print the
array 13.
14. for i in range(len(a)):
15. print (a[i], end = " ")
16.
17. a = [70, 15, 2, 51, 60]
18. print("Before sorting array elements are - ")
19. printArr(a)
20. insertionSort(a)
21. print("\nAfter sorting array elements are - ")
22. printArr(a)

Output:

Merge sort:

Merge Sort is a comparison-based sorting algorithm that works by dividing the input array into two
halves, then calling itself for these two halves, and finally it merges the two sorted halves. In this article,
we will learn how to implement merge sort in C language.
What is Merge Sort Algorithm?
Merge sort is based on the three principles: divide, conquer and combine which is better implemented
using recursion using two functions:
1. mergeSort() – For Divide
2. merge() – For Conquer and Combine
The mergeSort() function keeps dividing array into subarrays till it cannot be further divided (i.e. single
element). Then merge() function is called to merge two subarrays at a time in the required order until we
get back the whole array in the sorted order.
Time Complexity: O(n log(n) ) in all cases.
Auxiliary Space: O(n), as all elements are copied into an auxiliary array.

Implementation of Merge Sort in C


C language does not have inbuilt function for merge sort, so we have to manually implement it.

// C program for the implementation of merge sort

#include <stdio.h>
#include <stdlib.h>
// Merges two subarrays of arr[].
// First subarray is arr[left..mid]
// Second subarray is arr[mid+1..right]

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


int i, j, k;
int n1 = mid - left + 1;
int n2 = right - mid;
// Create temporary arrays
int leftArr[n1], rightArr[n2];
// Copy data to temporary arrays
for (i = 0; i < n1; i++)
leftArr[i] = arr[left + i];
for (j = 0; j < n2; j++)
rightArr[j] = arr[mid + 1 + j];
// Merge the temporary arrays back into arr[left..right]
i = 0;
j = 0;
k = left;
while (i < n1 && j < n2) {

if (leftArr[i] <= rightArr[j]) {


arr[k] = leftArr[i];
i++;
}
else {
arr[k] = rightArr[j];
j++;
}
k++;
}
// Copy the remaining elements of leftArr[], if any
while (i < n1) {
arr[k] = leftArr[i];
i++;
k++;
}
// Copy the remaining elements of rightArr[], if any
while (j < n2) {
arr[k] = rightArr[j];
j++;
k++;
}
}
// The subarray to be sorted is in the index range [left-right]
void mergeSort(int arr[], int left, int right) {
if (left < right) {
// Calculate the midpoint
int mid = left + (right - left) / 2;
// Sort first and second halves
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
// Merge the sorted halves
merge(arr, left, mid, right);
}
}
int main() {

int arr[] = { 12, 11, 13, 5, 6, 7 };


int n = sizeof(arr) / sizeof(arr[0]);
// Sorting arr using mergesort
mergeSort(arr, 0, n - 1);
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}

Output
Given array is
12 11 13 5 6 7

Sorted array is
5 6 7 11 12 13

Heap Sort:
What is a heap?
A heap is a complete binary tree, and the binary tree is a tree in which the node can have
the utmost two children. A complete binary tree is a binary tree in which all the levels
except the last level, i.e., leaf node, should be completely filled, and all the nodes should
be left-justified.
What is heap sort?
Heapsort is a popular and efficient sorting algorithm. The concept of heap sort is to
eliminate the elements one by one from the heap part of the list, and then insert them into
the sorted part of the list.
Heapsort is the in-place sorting algorithm.
Now, let's see the algorithm of heap sort.
Heap Sort Algorithm
Heap sort processes the elements by creating the min-heap or max-heap using the
elements of the given array. Min-heap or max-heap represents the ordering of array in
which the root element represents the minimum or maximum element of the array.
Heap sort basically recursively performs two main operations -
o Build a heap H, using the elements of array.
o Repeatedly delete the root element of the heap formed in 1st phase.
Algorithm
1. HeapSort(arr)
2. BuildMaxHeap(arr)
3. for i = length(arr) to 2
4. swap arr[1] with arr[i]
5. heap_size[arr] = heap_size[arr] ? 1
6. MaxHeapify(arr,1)
7. End
BuildMaxHeap(arr)
1. BuildMaxHeap(arr)
2. heap_size(arr) = length(arr)
3. for i = length(arr)/2 to 1
4. MaxHeapify(arr,i)
5. End
MaxHeapify(arr,i)
1. MaxHeapify(arr,i)
2. L = left(i)
3. R = right(i)
4. if L ? heap_size[arr] and arr[L] > arr[i]
5. largest = L
6. else
7. largest = i
8. if R ? heap_size[arr] and arr[R] > arr[largest]
9. largest = R
10. if largest != i
11. swap arr[i] with arr[largest]
12. MaxHeapify(arr,largest)
13. End
Working of Heap sort Algorithm
Now, let's see the working of the Heapsort Algorithm.
In heap sort, basically, there are two phases involved in the sorting of elements. By using
the heap sort algorithm, they are as follows -
o The first step includes the creation of a heap by adjusting the elements of the array.
o After the creation of heap, now remove the root element of the heap repeatedly by shifting
it to the end of the array, and then store the heap structure with the remaining elements.
Now let's see the working of heap sort in detail by using an example. To understand it
more clearly, let's take an unsorted array and try to sort it using heap sort. It will make the
explanation clearer and easier.

First, we have to construct a heap from the given array and convert it into max heap.

After converting the given heap into max heap, the array elements are -
Next, we have to delete the root element (89) from the max heap. To delete this node, we
have to swap it with the last node, i.e. (11). After deleting the root element, we again
have to heapify it to convert it into max heap.

After swapping the array element 89 with 11, and converting the heap into max-heap, the
elements of array are -

In the next step, again, we have to delete the root element (81) from the max heap. To
delete this node, we have to swap it with the last node, i.e. (54). After deleting the root
element, we again have to heapify it to convert it into max heap.

After swapping the array element 81 with 54 and converting the heap into max-heap, the
elements of array are -

In the next step, we have to delete the root element (76) from the max heap again. To
delete this node, we have to swap it with the last node, i.e. (9). After deleting the root
element, we again have to heapify it to convert it into max heap.
After swapping the array element 76 with 9 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (54) from the max heap. To
delete this node, we have to swap it with the last node, i.e. (14). After deleting the root
element, we again have to heapify it to convert it into max heap.

After swapping the array element 54 with 14 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (22) from the max heap. To
delete this node, we have to swap it with the last node, i.e. (11). After deleting the root
element, we again have to heapify it to convert it into max heap.
After swapping the array element 22 with 11 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (14) from the max heap. To
delete this node, we have to swap it with the last node, i.e. (9). After deleting the root
element, we again have to heapify it to convert it into max heap.

After swapping the array element 14 with 9 and converting the heap into max-heap, the
elements of array are -

In the next step, again we have to delete the root element (11) from the max heap. To
delete this node, we have to swap it with the last node, i.e. (9). After deleting the root
element, we again have to heapify it to convert it into max heap.

After swapping the array element 11 with 9, the elements of array are -

Now, heap has only one element left. After deleting it, heap will be empty.
After completion of sorting, the array elements are -

Now, the array is completely sorted.


Heap sort complexity
Now, let's see the time complexity of Heap sort in the best case, average case, and worst
case. We will also see the space complexity of Heapsort.
1. Time Complexity

Case Time Complexity

Best Case O(n logn)

Average Case O(n log n)

Worst Case O(n log n)

o BestCase Complexity - It occurs when there is no sorting required, i.e. the array is
already sorted. The best-case time complexity of heap sort is O(n logn).
o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time
complexity of heap sort is O(n log n).
o Worst Case Complexity - It occurs when the array elements are required to be sorted
in reverse order. That means suppose you have to sort the array elements in ascending
order, but its elements are in descending order. The worst-case time complexity of heap
sort is O(n log n).
The time complexity of heap sort is O(n logn) in all three cases (best case, average case,
and worst case). The height of a complete binary tree having n elements is logn.
2. Space Complexity

Space Complexity O(1)

Stable N0

o The space complexity of Heap sort is O(1).


Program: Write a program to implement heap sort in C language.
1. #include <stdio.h>
2. /* function to heapify a subtree. Here 'i' is the
3. index of root node in array a[], and 'n' is the size of heap. */
4. void heapify(int a[], int n, int i)
5. {
6. int largest = i; // Initialize largest as root
7. int left = 2 * i + 1; // left child
8. int right = 2 * i + 2; // right child
9. // If left child is larger than root
10. if (left < n && a[left] > a[largest])
11. largest = left;
12. // If right child is larger than root
13. if (right < n && a[right] > a[largest])
14. largest = right;
15. // If root is not largest
16. if (largest != i) {
17. // swap a[i] with a[largest]
18. int temp = a[i];
19. a[i] = a[largest];
20. a[largest] = temp;
21.
22. heapify(a, n, largest);
23. }
24. }
25. /*Function to implement the heap sort*/
26. void heapSort(int a[], int n)
27. {
28. for (int i = n / 2 - 1; i >= 0; i--)
29. heapify(a, n, i);
30. // One by one extract an element from heap
31. for (int i = n - 1; i >= 0; i--) {
32. /* Move current root element to end*/
33. // swap a[0] with a[i]
34. int temp = a[0];
35. a[0] = a[i];
36. a[i] = temp;
37.
38. heapify(a, i, 0);
39. }
40. }
41. /* function to print the array elements */
42. void printArr(int arr[], int n)
43. {
44. for (int i = 0; i < n; ++i)
45. {
46. printf("%d", arr[i]);
47. printf(" ");
48. }
49.
50. }
51. int main()
52. {
53. int a[] = {48, 10, 23, 43, 28, 26, 1};
54. int n = sizeof(a) / sizeof(a[0]);
55. printf("Before sorting array elements are - \n");
56. printArr(a, n);
57. heapSort(a, n);
58. printf("\nAfter sorting array elements are - \n");
59. printArr(a, n);
60. return 0;
61. }
Output
Quicksort Algorithm:
Sorting is a way of arranging items in a systematic manner. Quicksort is the widely used
sorting algorithm that makes n log n comparisons in average case for sorting an array of
n elements. It is a faster and highly efficient sorting algorithm. This algorithm follows
the divide and conquer approach. Divide and conquer is a technique of breaking down
the algorithms into subproblems, then solving the subproblems, and combining the
results back together to solve the original problem.
Divide: In Divide, first pick a pivot element. After that, partition or rearrange the array
into two sub-arrays such that each element in the left sub-array is less than or equal to
the pivot element and each element in the right sub-array is larger than the pivot
element.
Conquer: Recursively, sort two subarrays with Quicksort.
Combine: Combine the already sorted array.
Quicksort picks an element as pivot, and then it partitions the given array around the
picked pivot element. In quick sort, a large array is divided into two arrays in which one
holds values that are smaller than the specified value (Pivot), and another array holds
the values that are greater than the pivot.
After that, left and right sub-arrays are also partitioned using the same approach. It will
continue until the single element remains in the sub-array.

Choosing the pivot


Picking a good pivot is necessary for the fast implementation of quicksort. However, it
is typical to determine a good pivot. Some of the ways of choosing a pivot are as
follows -
o Pivot can be random, i.e. select the random pivot from the given array.
o Pivot can either be the rightmost element of the leftmost element of the given array.
o Select median as the pivot element.
Algorithm
Algorithm:
1. QUICKSORT (array A, start, end)
2. {
3. 1 if (start < end)
4. 2{
5. 3 p = partition(A, start, end)
6. 4 QUICKSORT (A, start, p - 1)
7. 5 QUICKSORT (A, p + 1, end)
8. 6}
9. }
Partition Algorithm:
The partition algorithm rearranges the sub-arrays in a place.
1. PARTITION (array A, start, end)
2. {
3. 1 pivot ? A[end]
4. 2 i ? start-1
5. 3 for j ? start to end -1 {
6. 4 do if (A[j] < pivot) {
7. 5 then i ? i + 1
8. 6 swap A[i] with A[j]
9. 7 }}
10. 8 swap A[i+1] with A[end]
11. 9 return i+1
12. }
Working of Quick Sort Algorithm
Now, let's see the working of the Quicksort Algorithm.
To understand the working of quick sort, let's take an unsorted array. It will make the
concept more clear and understandable.
Let the elements of array are -

In the given array, we consider the leftmost element as pivot. So, in this case, a[left] =
24, a[right] = 27 and a[pivot] = 24.
Since, pivot is at left, so algorithm starts from right and move towards left.
Now, a[pivot] < a[right], so algorithm moves forward one position towards left, i.e. -

Now, a[left] = 24, a[right] = 19, and a[pivot] = 24.


Because, a[pivot] > a[right], so, algorithm will swap a[pivot] with a[right], and pivot
moves to right, as -

Now, a[left] = 19, a[right] = 24, and a[pivot] = 24. Since, pivot is at right, so algorithm
starts from left and moves to right.
As a[pivot] > a[left], so algorithm moves one position to right as -
Now, a[left] = 9, a[right] = 24, and a[pivot] = 24. As a[pivot] > a[left], so algorithm
moves one position to right as -

Now, a[left] = 29, a[right] = 24, and a[pivot] = 24. As a[pivot] < a[left], so, swap
a[pivot] and a[left], now pivot is at left, i.e. -

Since, pivot is at left, so algorithm starts from right, and move to left. Now, a[left] = 24,
a[right] = 29, and a[pivot] = 24. As a[pivot] < a[right], so algorithm moves one position
to left, as -
Now, a[pivot] = 24, a[left] = 24, and a[right] = 14. As a[pivot] > a[right], so, swap
a[pivot] and a[right], now pivot is at right, i.e. -

Now, a[pivot] = 24, a[left] = 14, and a[right] = 24. Pivot is at right, so the algorithm
starts from left and move to right.

Now, a[pivot] = 24, a[left] = 24, and a[right] = 24. So, pivot, left and right are pointing
the same element. It represents the termination of procedure.
Element 24, which is the pivot element is placed at its exact position.
Elements that are right side of element 24 are greater than it, and the elements that are
left side of element 24 are smaller than it.
Now, in a similar manner, quick sort algorithm is separately applied to the left and right
sub-arrays. After sorting gets done, the array will be -

Quicksort complexity
Now, let's see the time complexity of quicksort in best case, average case, and in worst
case. We will also see the space complexity of quicksort.
1. Time Complexity

Case Time Complexity

Best Case O(n*logn)

Average Case O(n*logn)

Worst Case O(n2)

o Best Case Complexity - In Quicksort, the best-case occurs when the pivot element is
the middle element or near to the middle element. The best-case time complexity of quicksort
is O(n*logn).
o Average Case Complexity - It occurs when the array elements are in jumbled order
that is not properly ascending and not properly descending. The average case time complexity
of quicksort is O(n*logn).
o Worst Case Complexity - In quick sort, worst case occurs when the pivot element is
either greatest or smallest element. Suppose, if the pivot element is always the last element of
the array, the worst case would occur when the given array is sorted already in ascending or
descending order. The worst-case time complexity of quicksort is O(n2).
Though the worst-case complexity of quicksort is more than other sorting algorithms
such as Merge sort and Heap sort, still it is faster in practice. Worst case in quick sort
rarely occurs because by changing the choice of pivot, it can be implemented in
different ways. Worst case in quicksort can be avoided by choosing the right pivot
element.
2. Space Complexity

Space Complexity O(n*logn)


Stable NO

o The space complexity of quicksort is O(n*logn).


Implementation of quicksort
Now, let's see the programs of quicksort in different programming languages.
Program: Write a program to implement quicksort in C language.
1. #include <stdio.h>
2. /* function that consider last element as pivot,
3. place the pivot at its exact position, and place
4. smaller elements to left of pivot and greater
5. elements to right of pivot. */
6. int partition (int a[], int start, int end)
7. {
8. int pivot = a[end]; // pivot element
9. int i = (start - 1);
10.
11. for (int j = start; j <= end - 1; j++)
12. {
13. // If current element is smaller than the pivot
14. if (a[j] < pivot)
15. {
16. i++; // increment index of smaller element
17. int t = a[i];
18. a[i] = a[j];
19. a[j] = t;
20. }
21. }
22. int t = a[i+1];
23. a[i+1] = a[end];
24. a[end] = t;
25. return (i + 1);
26. }
27.
28. /* function to implement quick sort */
29. void quick(int a[], int start, int end) /* a[] = array to be sorted, start = Starting index, e
nd = Ending index */
30. {
31. if (start < end)
32. {
33. int p = partition(a, start, end); //p is the partitioning index
34. quick(a, start, p - 1);
35. quick(a, p + 1, end);
36. }
37. }
38.
39. /* function to print an array */
40. void printArr(int a[], int n)
41. {
42. int i;
43. for (i = 0; i < n; i++)
44. printf("%d ", a[i]);
45. }
46. int main()
47. {
48. int a[] = { 24, 9, 29, 14, 19, 27 };
49. int n = sizeof(a) / sizeof(a[0]);
50. printf("Before sorting array elements are - \n");
51. printArr(a, n);
52. quick(a, 0, n - 1);
53. printf("\nAfter sorting array elements are - \n");
54. printArr(a, n);
55.
56. return 0;
57. }
Output:

You might also like