All sorting algorithms ( detailed explanation )
Table of contents
Introduction
In this article, we are going to deep dive into the sorting algorithms. Sorting algos as the name suggests are used to sort arrays. There are mainly 7 types of sorting algorithms:
Selection sort
Bubble sort
Insertion sort
Merge sort
Quick sort
( In this article we will only be discussing Selection sort, bubble sort, and Insertion sort. Rest two algos we will discuss in another article )
Let's deep dive into each of the algorithms.
NOTE: while explaining the algorithm I would be following a pattern, in which first I would try to explain to you the algorithm, then I would write the pseudo code, after that I will do a dry run and then will give you the code of the algorithm.
Selection sort
In selection sort we pick the first element, then we consider that it has the smallest value, and then we traverse into the whole array trying to find any index that has the smallest value, then we simply swap the two indexes.
Confused?
Let's try to look at the pseudo-code.
for( int i = 0 ; i < arr.length - 1 ; i++ )
{
smallestIndex = i;
for( int j = i ; j < arr.length ; j++ )
{
if(arr[j] < arr[smallestIndex])
{
smallestIndex = j;
{
// swap values at smallestIndex and j
}
}
Let's try to understand with an example:
Let's consider this array : arr = { 8 , 5 , 0 ,1 }
For the first time
i
point at the index the0
, so thesmallestIndex
is currently0
. Now we enter the second loop. For the start of the second loop,j
is currently0
.Iteration 1:
j
is pointing at the index0
. Is the value at the indexj
smaller than the value at the indexsmallestIndex
? FALSEIteration 2:
j
is pointing at the index1
. Is the value at the indexj
smaller than the value at the indexsmallestIndex
? TRUE. NowsmallestIndex
is pointing at the index1
.Iteration 3:
j
is pointing at index 2. Is the value of the indexj
smaller than the value of the indexsmallestIndex
? TRUE. NowsmallestIndex
is pointing at the index2
.Iteration 4:
j
is pointing at index 3. Is the value at the indexj
smaller than the value at the indexsmallestIndex
? FALSESo after the first iteration, our
i
is pointing at the index0
and oursmallestIndex
is pointing at index 2, now we simply swap the values of these two indexes. So after swapping out the array, it looks somewhat like this:arr = { 0 , 5 , 8 , 1 }
Now for the second time,
i
will be at the index1
andsmallestIndex
will also point to index1
, and we would again do all the steps similarly, go into the second loop, and check if any index has any value smaller than the currentsmallestIndex
, if yes re-assign thesmallestIndex
value, and then swap the value. After the second iteration is over, our array will look somewhat like this:arr = { 0 , 1, 8 , 5 }
In the third iteration,
i
will be at the index2
and samesmallestIndex
will also point to the index2
. After you finish the iteration 3, our array will look alike:arr = { 0 , 1, 5 , 8}
And VOILLA, our array is sorted.
IMPORTANT NOTE: if you have noticed in the pseudo-code, for the first loop I am only iterating till the length - 2
index.
Let's understand with an example.
arr = { 3 ,4 , 6, 7, 8}
Let's say this is our array. For this array, the length of the array would be 5. So iterating till index - 2
means only iterating till index 3. We will not go till the last index because the last index would already be sorted as we put the biggest number at the last and also because if we look closely at the second loop we are traversing the array to compare other indexes, but at the last index we won't have any other element to compare with, so we only go till length - 2
.
Let's look at the code:
public class Solution {
public static void selectionSort(int[] arr) {
int length = arr.length;
for( int i = 0 ; i < length - 1 ; i++ ) {
int smallestIndex = i;
for( int j = i ; j < length ; j++ ){
if(arr[j] < arr[smallestIndex] ) {
smallestIndex = j;
}
}
int temp = arr[smallestIndex];
arr[smallestIndex] = arr[i];
arr[i] = temp;
}
}
}
The time complexity of this algo is O ( n ^ 2 ), and the space complexity is O ( N ).
Bubble sort
In bubble sort, we simply compare the two adjacent indexes and then place the smallest index on the left side and the bigger index on the right side.
NOTE: in selection sort, we used to move from left to right direction in the array, placing all the smaller numbers on the left side and the larger numbers on the right side. But in bubble sort we move from right to left, placing all the bigger numbers on the right side and the smaller numbers on the left side.
Let's look at the pseudo-code for a better understanding.
for( int i = arr.length - 1 ; i >= 1 ; i-- ) {
for(int j = 0 ; j < i ; j++ ) {
if(arr[j] > arr[j+1] {
// swap
}
}
}
Let's dry-run this code for a better understanding by taking a simple array.
arr = { 7 , 4 ,1 , 0 }
For the first time, the value of i will be
3
, so the loop will run 3 times. Then we enter the second loop where thej
is initialized0
and it will run till index2
.For the first time,
j
is0
, soarr[j]
gives us value7
andarr[j+1]
gives us value4
. Is7 > 4
? TRUE, swap occurs.arr = { 4 , 7 ,1 , 0 }
The second time,
j
is1
, soarr[j]
gives us value7
andarr[j+1]
gives us value1
. Is7 > 1
? TRUE, swap occurs.arr = { 4 , 1 ,7 , 0 }
For the third time,
j
is2
, soarr[j]
gives us value7
andarr[j+1]
gives us value0
. Is7 > 0
? TRUE, swap occurs.arr = { 4 , 1 ,0, 7 }
Exit from the outer loop (
i
loop). So you see after one iteration of the outer loop we managed to place the biggest value at the end.
For the second time, the value of
i
will be2
, so the loop will run 2 times. After completing the second iteration our array will look like this:arr = { 1 , 0 ,4, 7 }
The third time, the value
i
will be1
, so the loop will run 1 time. After completing the second iteration our array will look like this:arr = { 0, 1,4, 7 }
And the loop breaks, so our array is also sorted.
IMPORTANT NOTE: If you look close in the second loop instead of going till i
,I run the loop only till i - 1
, this is because if you don't do so the j
pointer will point at the last index of the array and will go on to compare the last index with j+1
value that does not exist, then it will return an error.
Code for this:
public class Solution {
public static void bubbleSort(int[] arr, int n) {
for( int i = n - 1 ; i>= 0 ; i--){
for(int j = 0 ; j < i ; j++) {
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
The time complexity of this algo is O ( n ^ 2 ), and the space complexity is O ( N ).
BUT, there is an exception in this algo, what if the array is already sorted?
arr = { 1, 2, 6, 8 }
In this case, what you can do is you can simply add a swap
variable in the second loop and initialize it to, and you can check if the value of the variable is 0
you can simply break the loop as the array is already sorted.
public class Solution {
public static void bubbleSort(int[] arr, int n) {
for( int i = n - 1 ; i>= 0 ; i--){
int swap = 0; // intialize a variable
for(int j = 0 ; j < i ; j++) {
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
swap++; // increment this on every swap
}
}
if(swap == 0 ) {
break;
}
}
}
}
In this case, if the array is already sorted, the TC would be O ( N )
Insertion sort
In insertion sort, we take a chunk of numbers from the array and then sort them individually. Like first we take one number, so one number is sorted in itself. Then we take two numbers and sort them. Then we take three numbers and sort them and so on.
Let's first look at its pseudo code:
for( i = 0 , i -> n ) {
int j = i;
while( j > 0 && ( arr[j -1] > arr[j] ) {
swap ( arr[j-1] , arr[j];
j--;
}
}
The pseudo-code is a little bit overwhelming, right?
Let's try to understand with an example.
arr = { 15, 14, 9, 8, 7 }
For the first time,
i
will be0
, so thej
will also point to the index0
and the while loop condition is not fulfilled, so we go to the next iteration.Second time
i
will be pointing at the index1
, so thej
will also point to the index1
, now in while loop:For the first time
j
is one, soj > 0
is true, andarr[j-1] > arr[j]
here is also true ( 15 > 14 ), so a swap occurs.arr = { 14, 15, 9, 8, 7 }
And after this
j
is reduced to0
and while the condition is not met, the loop breaks.
Third time
i
will point at the index2
, and soj
will also point at the index2
, so we enter the while loop:First time,
j
is2
, so isarr[1] > arr[2]
? TRUE, so a swap takes placearr = { 14, 9, 15, 8, 7 }
Then
j
is decremented.Second-time
j
is1
, so isarr[0] > arr[1]
? TRUE, so a swap takes placearr = { 9, 14, 15, 8, 7 }
Then
j
is decremented, andj
becomes0
, so while the loop breaks.
Fourth time
i
will point at the index3
, and soj
will also point at the index3
, so we enter the while loopFirst time
j
is3
, so isarr[2] > arr[3]
? TRUE, so a swap takes place.arr = { 9, 14, 8, 15, 7 }
Then j is decremented.
The second time
j
is2
, so isarr[1] > arr[2]
? TRUE, so a swap takes place.arr = { 9, 8, 14, 15, 7 }
Then j is decremented.
Third time
j
is1
, so isarr[0] > arr[1]
? TRUE, so a swap takes place.arr = { 8, 9, 14, 15, 7 }
Then j is decremented and
j
becomes0
and we exit the while loop
Similarly, for the fifth time
i
will point at the index4
and so willj
. After the while loop is completed our array will look something alikearr = { 7 ,8, 9, 14, 15 } , i.e our array will be sorted.
Wohhoo, our array is now sorted.
Now let's have a look at the actual code:
public class Solution {
public static void insertionSort(int[] arr, int size) {
for( int i = 0 ; i < size ; i++ ){
int j = i;
while(j > 0 && ( arr[j-1] > arr[j])){
int temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
j--;
}
}
}
}
The time complexity of this algo is O ( n ^ 2 ) but the best case is O ( N ) because if the array is already sorted only the outer loop will run and we will never go inside the while loop.
The space complexity is O ( 1 ).
Subscribe to my newsletter
Read articles from Manas Upadhyay directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Manas Upadhyay
Manas Upadhyay
I am a software engineer with nearly 2 years of experience with expertise in MERN stack.