Big factories knock on the door. Eight common sorting algorithms

Posted by drbigfresh on Thu, 17 Feb 2022 00:59:22 +0100

1, Algorithmic mind map

2, Algorithm classification


Time complexity and space complexity of the algorithm:

3, Bubble sorting

1. Basic thought

Compare the two adjacent numbers in turn, and put the smaller number in the front and the larger number in the back.

2. Dynamic rendering

3. Code implementation

//Bubble sorting
private static void bubbleSort(int[] arr){
    // Identification variable, indicating whether the exchange has taken place
    boolean flag = false;
    int temp = 0;
    for (int i = 0; i < arr.length-1; i++) {
        for (int j = 0; j < arr.length-1-i; j++) {
            // If the preceding number is larger than the following number, swap
            if(arr[j]>arr[j+1]){
                flag = true;
                temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
        // In one sort, no exchange has occurred
        if(!flag){
            break;
        }
    }
}

4. Speed test

Bubble sort: 120000 data, 23 seconds

4, Select sort

1. Basic thought

(1) Find the smallest element in the sequence and put it in the first position;

(2) Continue to find the smallest element from the remaining unordered elements and put it in the second position;

And so on until the sorting is completed.

2. Dynamic rendering

3. Code implementation

//Select sort
public static void selectSort(int[] arr) {
    for (int i = 0; i < arr.length - 1; i++) {
        int minIndex = i;
        int min = arr[minIndex];
        for(int j  = 1 + i;j<arr.length;j++){
            if(min > arr[j]){
                min = arr[j];
                minIndex = j;
            }
        }
        arr[minIndex] = arr[i];
        arr[i] = min;
    }
}

4. Speed test

Select sort: 120000 data, 4 seconds

5, Insert sort

1. Basic thought

Take the first place of n elements to be sorted as an ordered table and the others as an unordered table. In the sorting process, take a number from the unordered table each time, compare it with the number in the ordered table in turn, and insert it into the appropriate position.

2. Dynamic rendering

3. Code implementation

//Insert sort
public static void insertSort(int[] arr ){
    int insertVal = 0;
    int insertIndex = 0;
    for (int i = 1; i < arr.length; i++) {
        //Define the number of to be inserted
        insertVal = arr[i];
        // That is, the subscript of the number before arr[i]
        insertIndex = i - 1;
        // Find the insertion position for insertVal
        // explain
        // 1. Insertindex > = 0 ensure that the insertion position of insertVal is not exceeded
        // 2. Insertval < arr [insertindex] the number to be inserted, and the insertion position has not been found
        // 3. You need to move arr[insertIndex] backward
        while(insertIndex >= 0 && insertVal < arr[insertIndex]){
            arr[insertIndex+1] = arr[insertIndex];
            insertIndex--;
        }
        // When exiting the while loop, it indicates that the insertion position is found, insertIndex + 1
        if(insertIndex + 1 != i){
            arr[insertIndex+1] = insertVal;
        }
    }
}

4. Speed test

Insert sort: 120000 data, 1 second

6, Hill sort

1. Basic thought

Hill sort is also an insertion sort. It is a more efficient version of simple insertion sort after improvement, also known as reduced incremental sort. At the same time, the algorithm also breaks through O(n) ²) One of the first algorithms. It differs from insert sort in that it preferentially compares distant elements.

2. Renderings

3. Code example

Hill sort has two ways.

① Hill sort (bubble sort)

//Shell Sort 
// Use step-by-step derivation to write Hill sort
// In Hill sorting, the exchange method is adopted for the insertion of ordered sequences,
// Idea (algorithm) = = > code
public static void shellSort(int[] arr){
    // Based on the previous step-by-step analysis, cyclic processing is used
    for(int step = arr.length/2;step>0;step /= 2 ){
        for (int i = step; i < arr.length; i++) {
            // Traverse all elements in each group (a total of step groups, with elements in each group), step
            for (int j = i - step; j >= 0; j -= step) {
                // If the current element is larger than the element after adding the step size, it indicates the exchange
                if (arr[j] > arr[j + step]) {
                    int temp = arr[j];
                    arr[j] = arr[j + step];
                    arr[j + step] = temp;
                }
            }
        }
    }
}

Speed test:

Bubble Fasher sort: 120000 data, 11 seconds


② Hill sort (insert sort)

//Optimize Hill sort of exchange - > insert method
public static void shellSort2(int[] arr) {
// Increment step, and gradually reduce the increment
for (int step = arr.length / 2; step > 0; step /= 2) {
    // From the step element, directly insert and sort the groups one by one
    for (int i = step; i < arr.length; i++) {
        int j = i;
        int temp = arr[j];
        if(arr[j]<arr[j-step]){
            while (j - step >= 0&&temp<arr[j-step]){
                arr[j] = arr[j-step];
                j -= step;
            }
            arr[j] = temp;
        }
    }
}

Speed test:

Insert Fasher sort: 12000000 data, 4 seconds, amazing

7, Quick sort

1. Basic thought

The records to be arranged are divided into two independent parts through one-time sorting. If the keywords of one part of the records are smaller than those of the other part, the two parts of the records can be sorted respectively to achieve the whole sorting process.

2. Effect drawing

3. Algorithm description

  • Quick sort uses divide and conquer to divide a string into two substrings;
  • Find a datum point and temporarily select the middle point as the datum point;
  • Reorder the sequence, and put the smaller one in front of the datum point and the larger one behind the datum point;
  • Recursively sort the subsequence less than the benchmark value and the subsequence greater than the benchmark value;

4. Code example

//Quick sort
public static void quickSort(int[] arr,int left, int right) {
    int l = left; //Left subscript
    int r = right; //Right subscript
    //pivot axis value
    int pivot = arr[(left + right) / 2];
    int temp = 0; //Temporary variable, used in exchange
    //The purpose of the while loop is to put the value smaller than the pivot value to the left
    //Larger than pivot value, put to the right
    while( l < r) {
        //Keep looking on the left side of the pivot and exit only after finding a value greater than or equal to the pivot value
        while( arr[l] < pivot) {
            l += 1;
        }
        //Keep looking on the right side of pivot and exit only after finding a value less than or equal to pivot
        while(arr[r] > pivot) {
            r -= 1;
        }
        //If l > = R, it indicates that the left and right values of pivot are all on the left
        //Less than or equal to the pivot value, and all on the right are greater than or equal to the pivot value
        if( l >= r) {
            break;
        }
 
        //exchange
        temp = arr[l];
        arr[l] = arr[r];
        arr[r] = temp;
 
        //If after the exchange, it is found that this arr[l] == pivot value is equal to r --, move forward
        if(arr[l] == pivot) {
            r -= 1;
        }
        //If after the exchange, it is found that this arr[r] == pivot value is equal to l + +, move it back
        if(arr[r] == pivot) {
            l += 1;
        }
    }
 
    // If l == r, it must be l++, r --, otherwise stack overflow occurs
    if (l == r) {
        l += 1;
        r -= 1;
    }
    //Left recursion
    if(left < r) {
        quickSort(arr, left, r);
    }
    //Recursive right
    if(right > l) {
        quickSort(arr, l, right);
    }
}

5. Speed test

Quick sort: 12000000 data, 1 second, go against the sky

8, Merge sort

1. Basic thought

Merging and sorting adopts the classical divide and conquer strategy. The divide and conquer method divides the problem into some small problems and then solves them recursively. The stage of governance is to patch the answers obtained in the stages together, that is, divide and conquer.

2. Renderings


3. Code implementation

//Merge sort
public static void mergerSort(int[] arr,int left,int right,int[] temp){
    if(left<right){
        //Middle index
        int middle = (left + right)/2;
        //Decompose recursively to the left
        mergerSort(arr,left,middle,temp);
        //Decompose recursively to the right
        mergerSort(arr,middle + 1,right,temp);
        //merge
        merger(arr, left, middle, right, temp);
    }
}
 
//merge
public static void merger(int[] arr,int left,int middle,int right,int[] temp){
    int i = left; // Initialization i, the initial index of the left ordered sequence
    int j = middle + 1; //Initialization j, the initial index of the ordered sequence on the right
    int t = 0; // Points to the current index of the temp array
 
    //First, fill the left and right (ordered) data into the temp array according to the rules
    //Until one side of the ordered sequence on the left and right is processed
    while (i <= middle && j <= right) {//continue
        //If the current element of the left ordered sequence is less than or equal to the current element of the right ordered sequence
        //Fill the current element on the left into the temp array
        //Then t++, i++
        if(arr[i] <= arr[j]){
            temp[t] = arr[i];
            t++;
            i++;
        }else { //On the contrary, fill the current element of the ordered sequence on the right into the temp array
            temp[t] = arr[j];
            t++;
            j++;
        }
    }
 
    //Fill all the data on the side with remaining data into temp in turn
    //The ordered sequence on the left and the remaining elements are filled into temp
    while (i <= middle){
        temp[t] = arr[i];
        t++;
        i++;
    }
 
    //The ordered sequence on the right and the remaining elements are filled into temp
    while (j <= right){
        temp[t] = arr[j];
        t++;
        j++;
    }
 
    //Copy the elements of temp array to arr
    //Note that not all are copied every time
    t = 0;
    int tempLeft = left; //
    while (tempLeft <= right){
        arr[tempLeft] = temp[t];
        t++;
        tempLeft++;
    }
}

4. Speed test

Merge and sort: 12000000 data, 1 second, amazing

9, Cardinality sort

1. Basic thought

All values with comparison shall be unified into the same digit length, the number with shorter data shall be supplemented with 0, and then sorted in turn from the lowest order. In this way, after sorting from the lowest order to the highest order, the sequence will become an ordered sequence.

2. Code example

//Cardinality sort
public static void radixSort(int arr[]){
    System.out.println("Cardinality sort, arr length:"+arr.length);
    //1. Get the number of digits of the largest number in the array
    int max = arr[0]; //Suppose the first number is the maximum number
    for(int i = 1; i < arr.length; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    //What is the maximum number
    int maxLength = (max + "").length();
 
    //Define a two-dimensional array, representing 10 buckets, and each bucket is a one-dimensional array
    //explain
    //1. The two-dimensional array contains 10 one-dimensional arrays
    //2. In order to prevent data overflow when putting in numbers, the size of each one-dimensional array (bucket) is set to arr.length
    //3. The name is clear, and cardinality sorting is a classical algorithm that uses space for time
    int[][] bucket = new int[10][arr.length];
 
    //In order to record how many data are actually stored in each bucket, we define a one-dimensional array to record the number of data put in each bucket
    //It can be understood here
    //For example, bucketElementCounts[0] records the number of data put into the bucket[0]
    int[] bucketElementCounts = new int[10];
 
    //We will use the loop processing code here
    for(int i = 0 , n = 1; i < maxLength; i++, n *= 10) {
        //(sort the corresponding bits of each element). The first is a bit, the second is a ten bit, and the third is a hundred bit
        for(int j = 0; j < arr.length; j++) {
            //Take out the value of the corresponding bit of each element
            int digitOfElement = arr[j] / n % 10;
            //Put it into the corresponding bucket
            bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
            bucketElementCounts[digitOfElement]++;
        }
        //According to the order of this bucket (the subscript of one-dimensional array takes out the data in turn and puts it into the original array)
        int index = 0;
        //Traverse each bucket, and put the data in the bucket into the original array
        for(int k = 0; k < bucketElementCounts.length; k++) {
            //If there is data in the bucket, we put it into the original array
            if(bucketElementCounts[k] != 0) {
                //Cycle the bucket, i.e. the k-th bucket (i.e. the k-th one-dimensional array), and put it into
                for(int l = 0; l < bucketElementCounts[k]; l++) {
                    //Take out elements and put them into arr
                    arr[index++] = bucket[k][l];
                }
            }
            //After the i+1 round of processing, each bucket elementcounts [k] = 0!!!!
            bucketElementCounts[k] = 0;
 
        }
    }
}

3. Speed test

Cardinality sorting: 12000000 data, 1 second, moving speed

Topics: Algorithm data structure