Tagging education re learning data structure and algorithm 13 | sorting: Principle Analysis and advantages and disadvantages comparison of classical sorting algorithm

Keywords: Java Algorithm data structure

Learning resources: Pull hook Education

What is a ranking problem

  • Sorting - the process of turning a group of unordered data into order. Generally, the order here is from small to large by default
  • Measure the advantages and disadvantages of a sorting algorithm
    • Time complexity - specifically, the best time complexity, the worst time complexity, and the average time complexity
    • Spatial complexity - if the spatial complexity is 1, it is also called in place sorting
    • Stability refers to whether the order of equal data objects can be guaranteed to remain unchanged after sorting

Bubble sorting

  • The best time complexity is O(n), that is, when the input array is just in order, you only need to compare it one by one
  • The worst time complexity is O(n*n), that is, when the array is exactly in reverse order, each round of sorting needs to compare n one by one and repeat n times
  • When the input array is disordered, its average time complexity is O(n*n)
  • The spatial complexity is O(1)
  • stable
import java.util.Arrays;
public class Main {
    
    public static void main(String[] args) {
        
        int[] arr = { 1, 0, 3, 4, 5, -6, 7, 8, 9, 10 };
        System.out.println("raw data: " + Arrays.toString(arr));
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                } 
            }
        }
        System.out.println("Bubble sorting: " + Arrays.toString(arr));
    }
}

Insert sort

  • The best time complexity is O(n), that is, when the array is just in complete order, only one comparison can find the correct position interval each time
  • The worst time complexity is O(n*n), that is, when the array is exactly in reverse order, it needs to be compared n times each time to find the correct position interval
  • The average time complexity is O(n*n), because the average time complexity of inserting an element into the array is O(n), and insertion sorting can be understood as repeating the array insertion operation n times
  • The spatial complexity is O(1)
  • stable
import java.util.Arrays;
public class Main {
    
    public static void main(String[] args) {
        
    	int[] arr = { 2, 3, 5, 1, 23, 6, 78, 34 };
    	System.out.println("raw data: " + Arrays.toString(arr));
    	for (int i = 1; i < arr.length; i++) {
    		int temp = arr[i];
    		int j = i - 1;
    		for (; j >= 0; j--) {
    			if (arr[j] > temp) {
    				arr[j + 1] = arr[j];
    			} else {
    				break;
    			}
    		}
    		arr[j + 1] = temp;
    	}
    	System.out.println("Insert sort: " + Arrays.toString(arr));	
    }
}

Similarities and differences between insertion sort and bubble sort algorithms

  • Same point
    • The average time complexity of insertion sort and bubble sort is O(n*n), and both are stable sorting algorithms, which belong to in-situ sorting
  • Difference point
    • The exchange operation of each round of bubble sorting is dynamic, so three assignment operations are required to complete it
    • The exchange action of each round of insertion sorting will fix the data to be inserted, so only one-step assignment operation is required

Merge sort

  • The merging sort adopts the binary iterative method, and the complexity is logn. In each iteration, two ordered arrays need to be merged. Such an action can be completed under the time complexity of O(n). The complexity of merging sort is the product of O(nlogn). The best, worst and average time complexity of merging sort are O(nlogn)
  • The space complexity is O(n)
  • stable
import java.util.Arrays;
public class Main {
    
    public static void main(String[] args) {
        int[] arr = { 49, 38, 65, 97, 76, 13, 27, 50 };
        int[] tmp = new int[arr.length];
        System.out.println("raw data: " + Arrays.toString(arr));
        customMergeSort(arr, tmp, 0, arr.length - 1);
        System.out.println("Merge sort: " + Arrays.toString(arr));
    }
    public static void customMergeSort(int[] a, int[] tmp, int start, int end) {
        if (start < end) {
            int mid = (start + end) / 2;
            // Recursively sort the left subsequence
            customMergeSort(a, tmp, start, mid);
            // Recursively sort the right subsequence
            customMergeSort(a, tmp,mid + 1, end);
            // merge
            customDoubleMerge(a, tmp, start, mid, end);
        }
    }
    public static void customDoubleMerge(int[] a, int[] tmp, int left, int mid, int right) {
        int p1 = left, p2 = mid + 1, k = left;
        while (p1 <= mid && p2 <= right) {
            if (a[p1] <= a[p2])
                tmp[k++] = a[p1++];
            else
                tmp[k++] = a[p2++];
        }
        while (p1 <= mid)
            tmp[k++] = a[p1++];
        while (p2 <= right)
            tmp[k++] = a[p2++];
        // Copy back to element group
        for (int i = left; i <= right; i++)
            a[i] = tmp[i];
    }
}

Quick sort

  • The best time complexity is O(nlogn). If you can select the median every time you select a partition point and divide the array into two, the time complexity is O(nlogn)
  • The worst time complexity is O(n*n), that is, the minimum or maximum value is selected for each partition. To obtain two unequal groups, n partition operations are required. Each partition scans n/2 elements on average. At this time, the time complexity degrades to O(n*n)
  • The average time complexity is O(nlogn)
  • Space complexity is O(1)
  • instable
import java.util.Arrays;
public class Main {
    
    public static void main(String[] args) {
    	int[] arr = { 6, 1, 2, 7, 9, 11, 4, 5, 10, 8 };
    	System.out.println("raw data: " + Arrays.toString(arr));
    	customQuickSort(arr, 0, arr.length - 1);
    	System.out.println("Quick sort: " + Arrays.toString(arr));
    }
    public static void customQuickSort(int[] arr, int low, int high) {
    	int i, j, temp, t;
    	if (low >= high) {
    		return;
    	}
    	i = low;
    	j = high;
    	temp = arr[low];
    	while (i < j) {
    		// First look to the right and decrease to the left
    		while (temp <= arr[j] && i < j) {
    			j--;
    		}
    		// Look at the left and increase to the right
    		while (temp >= arr[i] && i < j) {
    			i++;
    		}
    		t = arr[j];
    		arr[j] = arr[i];
    		arr[i] = t;
    	}
    	arr[low] = arr[i];
    	arr[i] = temp;
    	// Recursive call to left half array
    	customQuickSort(arr, low, j - 1);
    	// Recursive call to right half array
    	customQuickSort(arr, j + 1, high);
    }
}

summary

  • For sorting data with small data scale, you can choose a sorting algorithm with time complexity of O(n*n)
  • To sort the data with large data scale, it is necessary to select a sorting algorithm with time complexity of O(nlogn)
    • The space complexity of merging and sorting is O(n), which also consumes a lot of space resources and is stable
    • The average time complexity of quick sort is O(nlogn), and the worst time complexity may approach O(n*n), which is unstable

Posted by barnbuster on Mon, 29 Nov 2021 07:52:34 -0800