Sorting - the most complete knowledge summary of seven sorting algorithms

Posted by NikLP on Fri, 11 Feb 2022 16:01:40 +0100

concept

Sorting: a series of records arranged in ascending or descending order according to the size of one or some keywords. Generally, sorting refers to sorting in place.

What is sort stability

Sorting stability: for two equal data, if the sorting algorithm can ensure that its relative position does not change after sorting, then the algorithm is a stable sorting.

Sorted classification overview

1. Insert sort

Direct insert sort

principle

The whole interval is divided into

  1. Ordered interval
  2. Disordered interval

Select the first element of the unordered interval every time and insert it at the appropriate position in the ordered interval

code implementation

public static void insertSort(int []array){
        for (int i = 1; i <array.length ; i++) {
            int tmp = array[i];
            int j = i-1;
            for (; j >=0 ; j--) {
                //If this is > = it is an unstable sort
                if (array[j]>tmp){
                    array[j+1] = array[j];
                }else {
                    array[j+1] = tmp;
                    break;
                }
            }
            array[j+1] = tmp;
        }
    }

performance analysis

Time complexitySpatial complexitystability
O(n^2)O(1)stable

Binary Insertion Sort

Shell Sort

principle

Hill ranking method is also known as reduced incremental method. The basic idea of hill sorting method is to select an integer first, divide all records in the file to be sorted into groups, divide all records with distance into the same group, and sort the records in each group. Then, take and repeat the above grouping and sorting. When arrival = 1, all records are arranged in a unified group.

  1. Hill sort is an optimization of direct insertion sort.
  2. When gap > 1, it is pre sorted, which aims to make the array closer to order. When gap == 1, the array is close to ordered, so it will be very easy
    Come on. In this way, the optimization effect can be achieved as a whole. We can compare the performance test after implementation.

code implementation

//Shell Sort 
    public static void shell(int [] array,int gap){
        for (int i = gap;i<array.length;i++){
            int tmp = array[i];
            int j = i-gap;
            for (; j >=0 ; j-=gap) {
                if (array[j] > tmp){
                    array[j+gap] = array[j];
                }else {
                    array[j+gap] = tmp;
                    break;
                }
            }
            array[j+gap] = tmp;
        }
    }
    public static void shellSort(int [] array){
        int [] drr = {5,3,1};

        for (int i = 0; i <array.length ; i++) {
            shell(array , i);
        }
    }

performance analysis

Time complexitySpatial complexitystability
O(n^2)O(1)instable

2. Select Sorting

Direct selection sorting

principle

Each time, the largest (or smallest) element is selected from the unordered interval and stored at the end (or front) of the unordered interval until all the data elements to be sorted are arranged.
The specific sorting process is as follows:

  1. The whole record sequence is divided into ordered area and unordered area. Initially, the ordered area is empty, and the unordered area contains all records to be sorted
  2. Select the record with the smallest key in the unordered area and compare it with the first element in the unordered area, so that the ordered area expands one record and the unordered area reduces one record
  3. Repeat step 2 until there is only one record left in the unordered area

Initial keyword: "8, 5, 2, 6, 9, 3, 1, 4, 0, 7"
After the first sorting: 0, "5, 2, 6, 9, 3, 1, 4, 8, 7"

After the second sequence: 0, 1, "2, 6, 9, 3, 5, 4, 8, 7"

After the third sorting: 0, 1, 2, "6, 9, 3, 5, 4, 8, 7"

After the fourth sequence: 0, 1, 2, 3, "9, 6, 5, 4, 8, 7"

"Sequence 1, 9, 2, 5, 6, 4, 4"

After the sixth sequence: 0, 1, 2, 3, 4, 5, "6, 9, 8, 7"

After the seventh sequence: 0, 1, 2, 3, 4, 5, 6, "9, 8, 7"

After the eighth sequence: 0, 1, 2, 3, 4, 5, 6, 7, "8, 9"

After the ninth sequence: 0, 1, 2, 3, 4, 5, 6, 7, 8, "9"

Results: "0, 1, 2, 3, 4, 5, 6, 7, 8, 9"

code implementation

public static void selectSort(int [] array){
        for (int i = 0; i < array.length - 1; i++) {
        // Unordered interval: [0, array.length - i)
        // Ordered interval: [array.length - i, array.length)
        int max = 0;
        for (int j = 1; j < array.length - i; j++) {
            if (array[j] > array[max]) {
                max = j;
           }
       }
        
        int t = array[max];
        array[max] = array[array.length - i - 1];
        array[array.length - i - 1] = t;
   }
 }

performance analysis

Time complexitySpatial complexitystability
O(n^2)O(1)instable

Heap sort

principle

The basic principle is also selective sorting, but instead of using traversal to find the maximum number of unordered intervals, it selects the maximum number of unordered intervals through heap.
Note: a lot should be built in ascending order; In descending order, small piles should be built.

code implementation

public void heapSort(){
        int end = this.elem.length-1;
        while (end > 0){
            //end is exchanged with the first element
            int tmp = this.elem[0];
            this.elem[0] = this.elem[end];
            this.elem[end] = tmp;
            //Rearrange after the exchange is completed
            adjustDown(0,end);
            //end move forward
            end--;
        }
    }
    
public void adjustDown(int parent,int len){
        int child = 2*parent+1;
        //Child < len means there are left children, but not necessarily right children
        while (child<len){
            //Child + 1 < len indicates a right child
            if (child+1<len&&this.elem[child]<this.elem[child+1]){
                child++;
            }
            //child must be the subscript of the maximum value of the left and right children
            if(this.elem[child]>this.elem[parent]){
                int tmp = this.elem[child];
                this.elem[child] = this.elem[parent];
                this.elem[parent] = tmp;
                parent = child;
                child = 2*parent+1;
            }else {
                //Starting from the last tree, as long as child = parent, there is no need to adjust later
                break;
            }
        }
    }

performance analysis

Time complexitySpatial complexitystability
O(n * log(n))O(1)instable

3. Exchange sorting

Bubble sorting

principle

In the unordered interval, through the comparison of adjacent numbers, bubble the largest number to the end of the unordered interval, and continue this process until the array is ordered as a whole

code implementation

performance analysis

Time complexitySpatial complexitystability
O(n^2)O(1)stable

Quick sort (important)

principle

  1. Select a number from the interval to be sorted as the benchmark value (pivot);
  2. Partition: traverse the entire range to be sorted, put the smaller (can contain equal) than the benchmark value to the left of the benchmark value, and put the larger (can contain equal) than the benchmark value to the right of the benchmark value;
  3. Using the idea of divide and conquer, the left and right cells are treated in the same way until the length between cells = = 1, which means that they are in order, or the length between cells = = 0, which means that there is no data.

code implementation

//Benchmarking function
    public static int pivot(int [] array,int start,int end){
        int tmp = array[start];
        while (start < end){
            while (start < end && array[end]>=tmp){
                end--;
            }
                array[start] = array[end];
            //Assign data to low
            while (start < end && array[start]<=tmp){
                start++;
            }
                array[end] = array[start];
        }
        //Finally, put the reference value at the meeting position
        array[start] = tmp;
        return start;
    }
    //Realize quick sorting
    public static void quick(int []array,int low,int high){
        if (low < high){
            int piv = pivot(array,low,high);
            //Divide and conquer recursively find the reference number on the left and right sides
            quick(array,low,piv-1);
            quick(array,piv+1,high);
        }
    }
    public static void quickSort(int [] array){
        quick(array,0,array.length-1);
    }

    
    

performance analysis

Time complexitySpatial complexity
bestaverageworstbestaverageworst
O(n * log(n))O(n * log(n))O(n^2)O(log(n))O(log(n))O(n)

stability

instable

4. Merge and sort

Merge sort

principle

Merge sort is an effective sorting algorithm based on merge operation. It is a very typical application of Divide and Conquer. Merge the ordered subsequences to obtain a completely ordered sequence; That is, each subsequence is ordered first, and then the subsequence segments are ordered. If two ordered tables are merged into one, it is called two-way merging.

code implementation

private static void merge(int[] array, int low, int mid, int high) {
        int i = low;
        int j = mid;
        int length = high - low;
        int[] extra = new int[length];
        int k = 0;

        // Select the small one and put it into extra 
        while (i < mid && j < high) {
            // Adding is equal to ensuring stability
            if (array[i] <= array[j]) {
                extra[k++] = array[i++];
            } else {
                extra[k++] = array[j++];
            }
        }

        // Put elements belonging to extra 
        while (i < mid) {
            extra[k++] = array[i++];
        }

        while (j < right) {
            extra[k++] = array[j++];
        }
       

        // Move from extra back to array 
        for (int t = 0; t < length; t++) {
            // It needs to be moved back to the original position, starting from low
            array[low + t] = extra[t];
        }
    }

public static void mergeSort(int[] array) {
        mergeSortInternal(array, 0, array.length);
    }
    // (the range to be sorted is [low, high) 
    private static void mergeSortInternal(int[] array, int low, int high) {
        if (low - 1 >= high) {
            return;
        }

        int mid = (low + high) / 2;
        mergeSortInternal(array, low, mid);
        mergeSortInternal(array, mid, high);

        merge(array, low, mid, high);
    }

performance analysis

Time complexitySpatial complexitystability
O(n * log(n))O(n)stable

Massive data sorting

External sorting: the sorting process needs to be performed in external storage such as disk
Premise: the memory is only 1G, and the data to be sorted is 100G
Because all data cannot be put down in memory, external sorting is required, and merge sorting is the most commonly used external sorting

  1. First, divide the documents into 200 copies, each 512 M
  2. Sort 512 M respectively, because the memory can be put down, so any sort method can be used
  3. Conduct 200 routes of merging and merge 200 ordered documents at the same time, and the final result will be orderly

5. Sorting summary

Sorting methodbestaverageworstSpatial complexitystability
Bubble sortingO(n)O(n^2)O(n^2)O(1)stable
Insert sortO(n)O(n^2)O(n^2)O(1)stable
Select sortO(n^2)O(n^2)O(n^2)O(1)instable
Shell Sort O(n)O(n^1.3)O(n^2)O(1)instable
Heap sortO(n * log(n))O(n * log(n))O(n * log(n))O(1)instable
Quick sortO(n * log(n))O(n * log(n))O(n^2)O(log(n)) ~ O(n)instable
Merge sortO(n * log(n))O(n * log(n))O(n * log(n))O(n)stable

Topics: Java Algorithm data structure quick sort