0% found this document useful (0 votes)
112 views16 pages

Merge Sort: Advantages and Disadvantages

Merge sort is a divide-and-conquer sorting algorithm that recursively divides an array into smaller subarrays, sorts them, and merges them back together. It has a time complexity of O(n log n) in all cases and is stable, making it suitable for large datasets and external sorting. However, it requires additional memory for temporary arrays, making it less efficient in terms of space compared to in-place algorithms like QuickSort.

Uploaded by

Prakash Sahu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
112 views16 pages

Merge Sort: Advantages and Disadvantages

Merge sort is a divide-and-conquer sorting algorithm that recursively divides an array into smaller subarrays, sorts them, and merges them back together. It has a time complexity of O(n log n) in all cases and is stable, making it suitable for large datasets and external sorting. However, it requires additional memory for temporary arrays, making it less efficient in terms of space compared to in-place algorithms like QuickSort.

Uploaded by

Prakash Sahu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Merge sort

Merge sort is a sorting algorithm that follows the divide-and-conquer approach.


It works by recursively dividing the input array into smaller subarrays and sorting
those subarrays then merging them back together to obtain the sorted array.
In simple terms, we can say that the process of merge sort is to divide the array
into two halves, sort each half, and then merge the sorted halves back together.
This process is repeated until the entire array is sorted.

How does Merge Sort work?


Merge sort is a popular sorting algorithm known for its efficiency and stability. It
follows the divide-and-conquer approach to sort a given array of elements.
Here’s a step-by-step explanation of how merge sort works:
1. Divide: Divide the list or array recursively into two halves until it can no more
be divided.
2. Conquer: Each subarray is sorted individually using the merge sort algorithm.
3. Merge: The sorted subarrays are merged back together in sorted order. The
process continues until all elements from both subarrays have been merged.
Let’s sort the array or list [38, 27, 43, 10] using Merge Sort

Divide:
 [38, 27, 43, 10] is divided into [38, 27 ] and [43, 10] .
 [38, 27] is divided into [38] and [27] .
 [43, 10] is divided into [43] and [10] .

Conquer:
 [38] is already sorted.
 [27] is already sorted.
 [43] is already sorted.
 [10] is already sorted.

Merge:
 Merge [38] and [27] to get [27, 38] .
 Merge [43] and [10] to get [10,43] .
 Merge [27, 38] and [10,43] to get the final sorted list [10, 27, 38, 43]
Therefore, the sorted list is [10, 27, 38, 43] .
// Java program for Merge Sort
import [Link].*;

class CUTM {

// Merges two subarrays of arr[].


// First subarray is arr[l..m]
// Second subarray is arr[m+1..r]
static void merge(int arr[], int l, int m, int r)
{
// Find sizes of two subarrays to be merged
int n1 = m - l + 1;
int n2 = r - m;

// Create temp arrays


int L[] = new int[n1];
int R[] = new int[n2];

// Copy data to temp arrays


for (int i = 0; i < n1; ++i)
L[i] = arr[l + i];
for (int j = 0; j < n2; ++j)
R[j] = arr[m + 1 + j];

// Merge the temp arrays

// Initial indices of first and second subarrays


int i = 0, j = 0;

// Initial index of merged subarray array


int k = l;
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[] if any


while (i < n1) {
arr[k] = L[i];
i++;
k++;
}

// Copy remaining elements of R[] if any


while (j < n2) {
arr[k] = R[j];
j++;
k++;
}
}

// Main function that sorts arr[l..r] using


// merge()
static void sort(int arr[], int l, int r)
{
if (l < r) {

// Find the middle point


int m = l + (r - l) / 2;

// Sort first and second halves


sort(arr, l, m);
sort(arr, m + 1, r);

// Merge the sorted halves


merge(arr, l, m, r);
}
}

// A utility function to print array of size n


static void printArray(int arr[])
{
int n = [Link];
for (int i = 0; i < n; ++i)
[Link](arr[i] + " ");
[Link]();
}

// Driver code
public static void main(String args[])
{
int arr[] = { 12, 11, 13, 5, 6, 7 };

[Link]("Given array is");


printArray(arr);
sort(arr, 0, [Link] - 1);

[Link]("\nSorted array is");


printArray(arr);
}
}

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.
o 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.
o [Link] in Java uses QuickSort
while [Link] 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 and Disadvantages of Merge Sort
Advantages
 Stability
: Merge sort is a stable sorting algorithm, which means it
maintains the relative order of equal elements in the input array.
 Guaranteed worst-case performance: Merge sort has a worst-case time
complexity of O(N logN) , which means it performs well even on large
datasets.
 Simple to implement: The divide-and-conquer approach is
straightforward.
 Naturally Parallel : We independently merge subarrays that makes it
suitable for parallel processing.
Disadvantages
 Space complexity: Merge sort requires additional memory to store the
merged sub-arrays during the sorting process.
 Not in-place: Merge sort is not an in-place sorting algorithm, which
means it requires additional memory to store the sorted data. This
can be a disadvantage in applications where memory usage is a
concern.
 Merge Sort is Slower than QuickSort in general as QuickSort is more
cache friendly because it works in-place.
QuickSort

QuickSort is a sorting algorithm based on the Divide and Conquer that picks an
element as a pivot and partitions the given array around the picked pivot by
placing the pivot in its correct position in the sorted array.

How does QuickSort Algorithm work?


QuickSort works on the principle of divide and conquer, breaking down the
problem into smaller sub-problems.
There are mainly three steps in the algorithm:
1. Choose a Pivot: Select an element from the array as the pivot. The choice of
pivot can vary (e.g., first element, last element, random element, or median).
2. Partition the Array: Rearrange the array around the pivot. After partitioning,
all elements smaller than the pivot will be on its left, and all elements greater
than the pivot will be on its right. The pivot is then in its correct position, and
we obtain the index of the pivot.
3. Recursively Call: Recursively apply the same process to the two partitioned
sub-arrays (left and right of the pivot).
4. Base Case: The recursion stops when there is only one element left in the sub-
array, as a single element is already sorted.

Choice of Pivot
There are many different choices for picking pivots.
 Always pick the first (or last) element as a pivot. The below implementation
picks the last element as pivot. The problem with this approach is it ends up in
the worst case when array is already sorted.
 Pick a random element as a pivot. This is a preferred approach because it does
not have a pattern for which the worst case happens.
 Pick the median element is pivot. This is an ideal approach in terms of time
complexity as we can find median in linear time and the partition function will
always divide the input array into two halves. But it takes more time on
average as median finding has high constants.
import [Link];

class CUTM {

// Partition function

static int partition(int[] arr, int low, int high) {

// Choose the pivot

int pivot = arr[high];

// Index of smaller element and indicates

// the right position of pivot found so far

int i = low - 1;

// Traverse arr[low..high] and move all smaller

// elements to the left side. Elements from low to

// i are smaller after every iteration

for (int j = low; j <= high - 1; j++) {

if (arr[j] < pivot) {

i++;

swap(arr, i, j);

}
// Move pivot after smaller elements and

// return its position

swap(arr, i + 1, high);

return i + 1;

// Swap function

static void swap(int[] arr, int i, int j) {

int temp = arr[i];

arr[i] = arr[j];

arr[j] = temp;

// The QuickSort function implementation

static void quickSort(int[] arr, int low, int high) {

if (low < high) {

// pi is the partition return index of pivot

int pi = partition(arr, low, high);

// Recursion calls for smaller elements

// and greater or equals elements

quickSort(arr, low, pi - 1);

quickSort(arr, pi + 1, high);
}

public static void main(String[] args) {

int[] arr = {10, 7, 8, 9, 1, 5};

int n = [Link];

quickSort(arr, 0, n - 1);

for (int val : arr) {

[Link](val + " ");

Complexity Analysis of Quick Sort


Time Complexity:
 Best Case: (Ω(n log n)), Occurs when the pivot element divides
the array into two equal halves.
 Average Case (θ(n log n)), On average, the pivot divides the
array into two parts, but not necessarily equal.
 Worst Case: (O(n²)), Occurs when the smallest or largest element
is always chosen as the pivot (e.g., sorted arrays).
Auxiliary Space: O(n), due to recursive call stack
Please refer Time and Space Complexity Analysis of Quick Sort for
more details.
Advantages of Quick Sort
 It is a divide-and-conquer algorithm that makes it easier to solve
problems.
 It is efficient on large data sets.
 It has a low overhead, as it only requires a small amount of
memory to function.
 It is Cache Friendly as we work on the same array to sort and do
not copy data to any auxiliary array.
 Fastest general purpose algorithm for large data when stability is
not required.
 It is tail recursive and hence all the tail call optimization can be
done.
Disadvantages of Quick Sort
 It has a worst-case time complexity of O(n2), which occurs when
the pivot is chosen poorly.
 It is not a good choice for small data sets.
 It is not a stable sort, meaning that if two elements have the same
key, their relative order will not be preserved in the sorted output
in case of quick sort, because here we are swapping elements
according to the pivot’s position (without considering their
original positions).

Binary Search Algorithm

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).
What is Binary Search Algorithm?
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.
Conditions to apply Binary Search Algorithm in a Data
Structure
To apply Binary Search algorithm:
 The data structure must be sorted.
 Access to any element of the data structure should take constant time.

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.
Complexity Analysis of Binary Search Algorithm
 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.
// Java implementation of recursive Binary Search

class BinarySearch {
// Returns index of x if it is present in arr[low..

// high], else return -1

int binarySearch(int arr[], int low, int high, int x)

if (high >= low) {

int mid = low + (high - low) / 2;

// If the element is present at the

// middle itself

if (arr[mid] == x)

return mid;

// If element is smaller than mid, then

// it can only be present in left subarray

if (arr[mid] > x)

return binarySearch(arr, low, mid - 1, x);

// Else the element can only be present

// in right subarray

return binarySearch(arr, mid + 1, high, x);


}

// We reach here when element is not present

// in array

return -1;

// Driver code

public static void main(String args[])

BinarySearch ob = new BinarySearch();

int arr[] = { 2, 3, 4, 10, 40 };

int n = [Link];

int x = 10;

int result = [Link](arr, 0, n - 1, x);

if (result == -1)

[Link](

"Element is not present in array");

else

[Link](
"Element is present at index " + result);

Common questions

Powered by AI

Both Merge Sort and QuickSort use the divide-and-conquer approach to enhance their efficiency by breaking down the problem into smaller subproblems and recursively solving them . Merge Sort divides the array into halves, sorts each half, and then merges the sorted halves, which ensures stability and a predictable time complexity of O(n log n). QuickSort, on the other hand, selects a pivot and rearranges the array such that elements less than the pivot precede elements greater than the pivot, which can potentially make it faster due to its in-place sorting and better cache utilization . The critical difference lies in their space complexities and stability, with Merge Sort being stable but requiring more memory, while QuickSort is more memory-efficient but not stable .

Merge Sort requires O(n) auxiliary space due to the need for additional temporary arrays during the merging process, which can be a drawback in memory-constrained applications . In contrast, QuickSort is generally more space-efficient, needing O(log n) auxiliary space for the recursive call stack, making it more suitable for scenarios where memory usage is a concern . The choice between these algorithms often depends on the trade-off between memory usage and other factors like stability or simplicity of implementation .

Merge Sort is advantageous for sorting large datasets due to its stability, guaranteed worst-case time complexity of O(n log n), and its ability to be easily parallelized since subarrays can be independently processed with the divide-and-conquer approach . However, it has significant disadvantages such as higher space complexity due to the need for additional memory to store temporary array data during the merging process, and it is slower than QuickSort for practical purposes because it is not in-place, requiring more memory operations .

Merge Sort is particularly advantageous for external sorting because of its ability to handle large datasets that do not fit completely into memory . Its divide-and-conquer approach allows for efficient management and merging of smaller sorted runs generated from chunks of data that can be loaded into memory separately, often outperforming other sorting algorithms in such disk-based operations . Additionally, its stability and predictable O(n log n) time complexity make it a reliable choice for such scenarios, despite its space complexity .

Binary Search is widely used in modern computing applications such as database querying, machine learning algorithms for optimizing parameters, and computer graphics for operations like ray tracing . It is preferred over linear search for large datasets because of its significantly lower time complexity of O(log N) compared to O(N) for linear search, making it much faster for large, sorted datasets . This efficiency becomes crucial when handling extensive amounts of data stored in external memory or cloud environments .

The efficiency of Binary Search is heavily influenced by whether the data structure is sorted and the ease of accessing elements in constant time . The sorted order of data is crucial because Binary Search divides the search space in half by comparing the middle element with the target, allowing it to eliminate half the potential matches at every step . Without a sorted array, the logic behind these eliminations would not hold, and the search would not correctly narrow down the possibilities to find the target efficiently .

QuickSort's in-place nature significantly enhances its performance as it sorts the array by partitioning in place without requiring additional arrays, unlike Merge Sort, which necessitates extra space for merging subarrays . This in-place sorting minimizes memory usage and improves cache performance because the algorithm maintains spatial locality, meaning that data elements are frequently accessed closely in memory, reducing cache misses and improving speed . This advantage makes QuickSort more cache-friendly relative to Merge Sort, which requires multiple memory accesses during the merge process .

Merge Sort is considered a stable sorting algorithm because it maintains the relative order of elements with equal keys as they appear in the input array . This stability is beneficial in scenarios where it's important to preserve the order of records with equal sorting keys, such as sorting a database table where multiple records have the same key but different secondary attributes, which is crucial in applications involving linked lists or non-primitive type sorting .

Recursion in QuickSort affects space complexity as each recursive call adds to the call stack, resulting in O(n) space usage in the worst case, such as when an unbalanced partition occurs . However, on average, QuickSort has a space complexity of O(log n) due to the balanced nature of partitions given a good pivot choice and tail call optimizations . Compared to iterative sorting methods, which typically employ a constant amount of auxiliary space, recursion in QuickSort can be advantageous due to logical clarity and less overhead when deeply nested stacks are avoided, although iterative approaches might be better in severely memory-constrained environments .

The choice of pivot in QuickSort affects its performance significantly. A poorly chosen pivot can lead to unbalanced partitions and a worst-case time complexity of O(n^2), as would occur with a consistently smallest or largest element as the pivot . An ideal strategy for selecting pivots is to use a random element or the median, which helps in dividing the array into approximately equal halves, thereby improving average case performance to O(n log n).

You might also like