Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

AOA Experiment 02

Name: Trushant Narwani Roll No.: 1902114


Date: 22-02-2021 Batch: C23
Quick Sort:
Aim:
To Implement Quick Sort algorithm.

Theory:
Quick Sort is one of the different sorting techniques which is based on the concept of divide
and conquer, just like merge sort. But in quick sort all the heavy lifting(major work) is done
while dividing the array into subarrays, while in case of merge sort, all the real work
happens during merging the subarrays. In case of quick sort, the combine step does
absolutely nothing.
It is also called partition-exchange sort. This algorithm divides the list into three main parts:

1. Elements less than the pivot element


2. Pivot element(Central element)
3. Elements greater than the pivot element

Pivot element can be any element from the array, it can be the first element, the last
element or any random element. In this tutorial, we will take the rightmost element or the
last element as pivot.

Following are the steps involved in quick sort algorithm:

1. After selecting an element as pivot, which is the last index of the array in our case,
we divide the array for the first time.
2. In quick sort, we call this partitioning. It is not simple breaking down of array into 2
subarrays, but in case of partitioning, the array elements are so positioned that all
the elements smaller than the pivot will be on the left side of the pivot and all the
elements greater than the pivot will be on the right side of it.
3. And the pivot element will be at its final sorted position.
4. The elements to the left and right, may not be sorted.
5. Then we pick subarrays, elements on the left of pivot and elements on the right
of pivot, and we perform partitioning on them by choosing a pivot in the subarrays.

Example:
Consider the following array: 50, 23, 9, 18, 61, 32. We need to sort this array in the most
efficient manner without using extra place (in place sorting).
Solution
Step 1:

 Make any element as pivot: Decide any value to be the pivot from the list. For
convenience of code, we often select the rightmost index as pivot or select any at
random and swap with rightmost. Suppose for two values “Low” and “High”
corresponding to the first index and last index respectively.
 In our case low is 0 and high is 5.
 Values at low and high are 50 and 32 and value at pivot is 32.

 Partition the array on the basis of pivot: Call for partitioning which rearranges the
array in such a way that pivot (32) comes to its actual position (of the sorted array).
And to the left of the pivot, the array has all the elements less than it, and to the
right greater than it.
 In the partition function, we start from the first element and compare it with
the pivot. Since 50 is greater than 32, we don’t make any change and move
on to the next element 23.
 Compare again with the pivot. Since 23 is less than 32, we swap 50 and 23.
The array becomes 23, 50, 9, 18, 61, 32.
 We move on to the next element 9 which is again less than pivot (32) thus
swapping it with 50 makes our array as 23, 9, 50, 18, 61, 32.
 Similarly, for next element 18 which is less than 32, the array becomes 23, 9,
18, 50, 61, 32. Now 61 is greater than pivot (32), hence no changes.
 Lastly, we swap our pivot with 50 so that it comes to the correct position.
Thus the pivot (32) comes at its actual position and all elements to its left are lesser, and all
elements to the right are greater than itself.

Step 2:
The main array after the first step becomes
23, 9, 18, 32, 61, 50
Step 3:
Now the list is divided into two parts:
1. Sublist before pivot element
2. Sublist after pivot element

Step 4:
Repeat the steps for the left and right sublists recursively. The final array thus becomes
9, 18, 23, 32, 50, 61.

Complexity Analysis:
Time Complexities
 Worst Case Complexity [Big-O]: O(n2)
It occurs when the pivot element picked is either the greatest or the smallest
element.
This condition leads to the case in which the pivot element lies in an extreme end of
the sorted array. One sub-array is always empty and another sub-array contains n - 1
elements. Thus, quicksort is called only on this sub-array.
However, the quick sort algorithm has better performance for scattered pivots.
 Best Case Complexity [Big-omega]: O(n*log n)
It occurs when the pivot element is always the middle element or near to the middle
element.
 Average Case Complexity [Big-theta]: O(n*log n)
It occurs when the above conditions do not occur.

Space Complexity
The space complexity for quicksort is O(log n).

Conclusion

Overall Quick Sort is an important concept to understand when it comes to algorithms.


Program:
import java.util.*;
class Main
{
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.println("Enter number of elements in the array");
int n = sc.nextInt();

int a[] = new int[n];


System.out.println("enter an unsorted array");
for(int k=0;k<n;k++){
a[k]=sc.nextInt();
}
System.out.println();
System.out.println("unsorted array : ");
for(int k=0;k<n;k++){
System.out.print(a[k]+" ");
}
System.out.println();
sort(a,0,a.length -1);
System.out.println("Sorted array using Quick sort");
for(int i=0;i<a.length;i++)
System.out.print(a[i]+" ");
}
public static void sort(int a[], int lb,int ub){

int pos = partition(a,lb,ub);


if(lb < pos-1)
sort(a,lb,pos-1);
if(pos < ub)
sort(a,pos,ub);

}
public static int partition(int a[],int start,int end)
{

int pivot = a[(start + end )/2];


while(start <= end)
{
while(a[start] < pivot)
start=start + 1;
while(a[end] > pivot)
end = end -1;
if(start <= end )
{
int t = a[start];
a[start] = a[end];
a[end] = t;
start++;
end--;
}
}
printarr(a);
return start;
}
public static void printarr(int arr[]){
for (int i : arr){
System.out.print(i+" ");

}
System.out.println();
}

Output:
Merge Sort:
Aim:
To Implement Merge Sort algorithm.

Theory:
Merge sort is one of the most efficient sorting algorithms. It works on the principle of divide
and conquer. Merge sort repeatedly breaks down a list into several sublists until each sublist
consists of a single element and merging those sublists in a manner that results into a sorted
list.
In merge sort, we break the given array midway, for example if the original array had 6
elements, then merge sort will break it down into two subarrays with 3 elements each.
But breaking the original array into 2 smaller subarrays is not helping us in sorting the array.
So, we will break these subarrays into even smaller subarrays, until we have multiple
subarrays with single element in them. Now, the idea here is that an array with a single
element is already sorted, so once we break the original array into subarrays which has only
a single element, we have successfully broken down our problem into base problems. And
then we have to merge all these sorted subarrays, step by step to form one single sorted
array.

Algorithm:
MergeSort(arr, left, right):
if left > right
return
mid = (left+right)/2
mergeSort(arr, left, mid)
mergeSort(arr, mid+1, right)
merge(arr, left, mid, right)
end
Example:

Let's start with array holding [14, 7, 3, 12, 9, 11, 6, 2], so that the first subarray is actually
the full array, array[0..7] (p=0p=0p, equals, 0 and r=7r=7r, equals, 7). This subarray has at
least two elements, and so it's not a base case.

 In the divide step, we compute q = 3q=3q, equals, 3.


 The conquer step has us sort the two subarrays array[0..3], which contains [14, 7, 3, 12],
and array[4..7], which contains [9, 11, 6, 2]. When we come back from the conquer step,
each of the two subarrays is sorted: array[0..3] contains [3, 7, 12, 14]
and array[4..7] contains [2, 6, 9, 11], so that the full array is [3, 7, 12, 14, 2, 6, 9, 11].
 Finally, the combine step merges the two sorted subarrays in the first half and the second
half, producing the final sorted array [2, 3, 6, 7, 9, 11, 12, 14].
How did the subarray array[0..3] become sorted? The same way. It has more than two
elements, and so it's not a base case. With p=0p=0p, equals, 0 and r=3r=3r, equals, 3,
compute q=1q=1q, equals, 1, recursively sort array[0..1] ([14, 7]) and array[2..3] ([3, 12]),
resulting in array[0..3] containing [7, 14, 3, 12], and merge the first half with the second half,
producing [3, 7, 12, 14].

How did the subarray array[0..1] become sorted? With p=0p=0p, equals, 0 and r=1r=1r,
equals, 1, compute q=0q=0q, equals, 0, recursively sort array[0..0] ([14])
and array[1..1] ([7]), resulting in array[0..1] still containing [14, 7], and merge the first half
with the second half, producing [7, 14].

Complexity Analysis:
Time Complexities
Merge Sort is quite fast, and has a time complexity of O(n*log n). It is also a stable sort,
which means the "equal" elements are ordered in the same order in the sorted list.
Similar to Binary Search, whenever we divide a number into half in every step, it can be
represented using a logarithmic function, which is log n and the number of steps can be
represented by log n + 1(at most)
Also, we perform a single step operation to find out the middle of any subarray, i.e. O(1).
And to merge the subarrays, made by dividing the original array of n elements, a running
time of O(n) will be required.
Hence the total time for mergeSort function will become n(log n + 1), which gives us a time
complexity of O(n*log n).
Worst Case Time Complexity [ Big-O ]: O(n*log n)
Best Case Time Complexity [Big-omega]: O(n*log n)
Average Time Complexity [Big-theta]: O(n*log n)

Space Complexity
When combining two sorted arrays into a single bigger one, we need scratch space to hold
the merged result.
Since the arrays we'll be combining have O(n) items, we'll need O(n) space in total.

Conclusion
Overall Merge Sort is an important concept to understand when it comes to algorithms.

Program:
import java.util.*;
class Main
{
void merge(int arr[], int beg, int mid, int end)
{

int l = mid - beg + 1;


int r = end - mid;

int LeftArray[] = new int [l];


int RightArray[] = new int [r];

for (int i=0; i<l; ++i)


LeftArray[i] = arr[beg + i];

for (int j=0; j<r; ++j)


RightArray[j] = arr[mid + 1+ j];

int i = 0, j = 0;
int k = beg;
while (i<l&&j<r)
{
if (LeftArray[i] <= RightArray[j])
{
arr[k] = LeftArray[i];
i++;
}
else
{
arr[k] = RightArray[j];
j++;
}
k++;
}
while (i<l)
{
arr[k] = LeftArray[i];
i++;
k++;
}

while (j<r)
{
arr[k] = RightArray[j];
j++;
k++;
}
display(arr);
}

void sort(int arr[], int beg, int end)


{
if (beg<end)
{
int mid = (beg+end)/2;
sort(arr, beg, mid);
sort(arr , mid+1, end);
merge(arr, beg, mid, end);
}
}
void display(int arr[])
{
for(int i =0; i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
System.out.println();
}
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
System.out.println("enter no of elements");
int n = sc.nextInt();

int arr[] = new int[n];


System.out.println("enter the elements");
for(int i=0;i<n;i++)
{
arr[i]=sc.nextInt();
}
Main ob = new Main();
ob.sort(arr, 0, arr.length-1);

System.out.println("\nSorted array");
for(int i =0; i<arr.length;i++)
{
System.out.print(arr[i]+" ");
}
}
}

Output:

You might also like