Searching and Sorting
Merge Sort Example
/* Java program for Merge Sort */ class MergeSort { // Merges two subarrays of arr[]. // First subarray is arr[l..m] // Second subarray is arr[m+1..r] 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 indexes of first and second subarrays int i = 0, j = 0; // Initial index of merged subarry 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() void sort(int arr[], int l, int r) { if (l < r) { // Find the middle point int m = (l+r)/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 = arr.length; for (int i=0; i<n; ++i) System.out.print(arr[i] + " "); System.out.println(); } // Driver method public static void main(String args[]) { int arr[] = {12, 11, 13, 5, 6, 7}; System.out.println("Given Array"); printArray(arr); MergeSort ob = new MergeSort(); ob.sort(arr, 0, arr.length-1); System.out.println("\nSorted array"); printArray(arr); } }
Linear Search Steps
1. Start from the leftmost element of arr[ ] and one by one compare x with each element of arr[ ]. 2. If x matches with an element, return the index. 3. If x doesn't match with any element, return -1.
Merge Sort Steps
A divide and conquer algorithm Divides array into 2 halves, calls itself for the 2 halves then merges the 2 sorted halves. MergeSort(arr[], l, r) If r > l 1. Find the middle point to divide the array into two halves: middle m = (l+r)/2 2. Call mergeSort for first half: Call mergeSort(arr, l, m) 3. Call mergeSort for second half: Call mergeSort(arr, m+1, r) 4. Merge the two halves sorted in step 2 and 3: Call merge(arr, l, m, r)
Binary Insertion Sort Steps
Binary Insertion Sort find use binary search to find the proper location to insert the selected item at each iteration. In normal insertion, sort it takes O(i) (at ith iteration) in worst case. we can reduce it to O(logi) by using binary search. The algorithm as a whole still has a running worst case running time of O(n2) because of the series of swaps required for each insertion. 1) Create an empty sorted (or result) list 2) Traverse the given list, do following for every node. ......a) Insert current node in sorted way in sorted or result list. 3) Change head of given linked list to head of sorted (or result) list.
QuickSort Steps
Divide and conquer algorithm It picks an element as pivot and partitions the given array around the picked pivot. There are many different versions of quickSort that pick pivot in different ways. Always pick first element as pivot. Always pick last element as pivot (implemented below) Pick a random element as pivot. Pick median as pivot.
Binary Search Steps
Searches a sorted array 1. Compare x with the middle element. 2. If x matches with middle element, return the middle index. 3. Else if x is greater than the middle element, then x can only lie in the right half. Search that half recursively. 4. Else x is smaller and search the left half recursively.
ShellSort Steps
ShellSort 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 exchange of far items. In shellSort, 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 is sorted.
Selection Sort Steps
Sorts an array by repeatedly finding the minimum element from unsorted part and putting it at the beginning. Maintains 2 subarrays: the subarray that is already sorted and the remaining subarray which is unsorted.
QuickSort Analysis
Space Complexity: O(log n) Time Complexity: Worst: O(n^2) Average: O(n log n)
Selection Sort Analysis
Time Complexity: Average Case: Θ(n^2) Worst Case: O(n^2) Space Complexity: Worst Case: O(1) The good thing about selection sort is it never makes more than O(n) swaps and can be useful when memory write is a costly operation.
Insertion Sort Analysis
Time Complexity: O(n^2) Auxiliary Space: O(1) Used when number of elements is small or only a few elements are misplaced.
ShellSort Analysis
Time Complexity: Time complexity of above implementation of shellsort is O(n2). In the above implementation gap is reduce by half in every iteration. There are many other ways to reduce gap which lead to better time complexity. Space Complexity: O(1)
Linear Search Analysis
Time complexity is O(n). Time taken to search elements keep increasing as the number of elements are increased.
Bubble Sort Steps
Works by repeatedly swapping the adjacent elements if they are in wrong order. The algorithm needs one whole pass without any swaps to know it is sorted.
Bubble Sort Analysis
Worst Case Time Complexity: O(n^2) occurs when array is reversed sorted Best Case Time Complexity: O(n) when array is already sorted Auxiliary Space: O(1)
Binary Insertion Sort Analysis
Worst case: O(n^2) because of the series of swaps required for each insertion.
Binary Search Analysis
Worst-case space complexity: O(1) Worst-case performance: O(log n) Average performance: O(log n)