Detailed explanation of eight sorts of sorting

Posted by modulor on Sun, 20 Feb 2022 16:00:18 +0100

1 sorting overview

Let's take a look at the relationship between the eight sorts:

1.1 insert sort

1.1.1 direct insertion sort

1.1.1.1 definition

Basic idea: in a group of numbers to be sorted, suppose the front (n-1), in which [n > = 2] numbers are already in good order. Now insert the nth number into the front ordinal number to make the N numbers
It's also in order. Repeat this cycle until all are in order.

The principle of insertion sorting is very simple, just like when we play poker. If the card in hand is smaller than his previous card, continue to compare forward. When this card is larger than the card in front of him, it can be inserted behind him. Of course, in the computer, we also need to move the compared cards back one bit

As shown in the figure:

1.1.1.2 java implementation

public class insertSort {  
  public insertSort(){  
     Integer a[]={49,72,38,65,23};  
      int temp=0;  
      for(int i=1;i<a.length;i++){  
         int j=i-1;  
         temp=a[i];    
       for(;j>=0&&temp<a[j];j--){    
       a[j+1]=a[j];                       //Move the value greater than temp back one unit as a whole  
         }  
         a[j+1]=temp;
         System.out.println(StringUtils.join(a, ","));
      }
      //System.out.println(StringUtils.join(a, ","));         
   }  
}

Operation results
49,72,38,65,23
38,49,72,65,23
38,49,65,72,23
23,38,49,65,72 

1.1.2 Hill sort (minimum incremental sort)

1.1.2.1 definition

Basic idea: the algorithm first divides a group of numbers to be sorted into several groups according to a certain increment D (n/2,n is the number of numbers to be sorted), and the subscript difference of records in each group is d. all elements in each group are directly inserted and sorted, and then it is grouped with a smaller increment (d/2), and then directly inserted and sorted in each group. When the increment is reduced to 1, the sorting is completed after direct insertion sorting.
As shown in the figure:

1.1.2.2 java implementation

public class shellSort {    
public static void main(String[] args) {
        Integer a[]={1,54,6,3,78,34,12,45,56,100};

        double d1=a.length;
        int temp=0;
        while(true){
                d1= Math.ceil(d1/2);
            int d=(int) d1;
            for(int x=0;x<d;x++){
                for(int i=x+d;i<a.length;i+=d){
                    int j=i-d;
                    temp=a[i];
                    for(;j>=0&&temp<a[j];j-=d){
                        a[j+d]=a[j];
                    }
                    a[j+d]=temp;
                }
            }
            if(d==1)
                break;

            System.out.println(StringUtils.join(a, ","));
        }

    }
}
Operation results
1,12,6,3,78,34,54,45,56,100
1,12,6,3,45,34,54,78,56,100
1,3,6,12,45,34,54,78,56,100

1.2 selection and sorting

1.2.1 simple selection sorting

1.2.1.1 definition

Basic idea: in a group of numbers to be sorted, select the smallest number to exchange with the number in the first position; Then exchange the smallest number with the number in the second position among the remaining numbers, and cycle until the penultimate number is compared with the last number
As shown in the figure:

1.2.1.2 java implementation

public class selectSort {  
  public static void main(String[] args) {
        Integer a[] = {1, 54, 6, 3, 78, 34, 12, 45};
        int position = 0;
        for (int i = 0; i < a.length; i++) {
            int j = i + 1;

            position = i;
            int temp = a[i];
            for (; j < a.length; j++) {
                if (a[j] < temp) {
                    temp = a[j];
                    position = j;
                }
            }
            a[position] = a[i];
            a[i] = temp;

            System.out.println(StringUtils.join(a, ","));
        }
    } 
} 

Operation results
1,54,6,3,78,34,12,45
1,3,6,54,78,34,12,45
1,3,6,54,78,34,12,45
1,3,6,12,78,34,54,45
1,3,6,12,34,78,54,45
1,3,6,12,34,45,54,78
1,3,6,12,34,45,54,78
1,3,6,12,34,45,54,78 

1.2.2 heap sorting

1.2.2.1 definition

Basic idea: heap sort is a tree selection sort, and the bottom layer is an approximate complete binary tree, which is an effective improvement on direct selection sort.
The definition of heap is as follows: a sequence with n elements (h1,h2,...,hn) is called heap if and only if it satisfies (HI > = h2i, hi > = 2I + 1) or (HI < = h2i, hi < = 2I + 1) (i=1,2,...,n/2).
Only the heap satisfying the former condition is discussed here. It can be seen from the definition of heap that the top element (i.e. the first element) must be the largest item (large top heap).
Complete binary tree can intuitively represent the structure of heap. The top of the heap is the root, and the others are the left subtree and the right subtree. Initially, the sequence of numbers to be sorted is regarded as a sequentially stored binary tree, and their storage order is adjusted to make it a heap. At this time, the number of root nodes of the heap is the largest. The root node is then swapped with the last node in the heap. Then readjust the previous (n-1) number to make it a heap. And so on, until the heap with only two nodes, and exchange them, and finally get an ordered sequence with n nodes.
From the description of the algorithm, heap sorting requires two processes:
The first is to establish the heap, and the second is to exchange the position between the top of the heap and the last element of the heap. So heap sorting consists of two functions. One is the penetration function of heap building, and the other is the function of repeatedly calling the penetration function to realize sorting.

Supplement:

  • Principle of large top heap: the keyword of the root node (also known as the top of the heap) is the largest of all node keywords in the heap, which is called large top heap. The large top heap requires that the keyword of the root node is greater than or equal to the keyword value of both the left subtree and the right subtree
  • Principle of small top heap: the keyword of the root node (also known as the top of the heap) is the smallest of all node keywords in the heap, which is called small top heap. Small heap requires that the keyword of the root node is less than or equal to the keyword value of both the left subtree and the right subtree
  • The index value of the last leaf node is n-1, and the location of the last non leaf node is n/2-1. N is the total number of nodes in the complete binary tree
  • Count from 0. The index value is node i. the left child position is 2*i+1 and the right child position is 2*i+2
    As shown in the figure:
    Initial sequence: 46,79,56,38,40,84
    Reactor building:

    Swap, kicking the maximum number from the heap

    The remaining nodes rebuild the heap, and then exchange and kick out the maximum number

    And so on: the last two remaining nodes in the last heap are exchanged, one is kicked out, and the sorting is completed.

1.2.2.2 java implementation

Examples of heap sorting and subscript indexing:

Examples of large and small top piles:

import java.util.Arrays;  
public class HeapSort {  
     int a[]={49,38,65,97,76,13,27,49};    
    public  HeapSort(){    
       heapSort(a);    
    }    
    public  void heapSort(int[] a){    
        System.out.println("Start sorting");  
          int arrayLength=a.length;    
        //Cyclic reactor building    
        for(int i=0;i<arrayLength-1;i++){  
             //Build pile  
              buildMaxHeap(a,arrayLength-1-i);  
              //Swap the top of the heap and the last element  
             swap(a,0,arrayLength-1-i);  
              System.out.println(Arrays.toString(a));  
          }   
    }  
  
    private  void swap(int[] data, int i, int j) {  
        // TODO Auto-generated method stub    
        int tmp=data[i];    
        data[i]=data[j];  
          data[j]=tmp;    
    }  
  
    //Build a large top heap for the data array from 0 to lastIndex   
    private void buildMaxHeap(int[] data, int lastIndex) {    
        // TODO Auto-generated method stub  
        //Start with the parent node of the node (the last node) at lastIndex   
        for(int i=(lastIndex-1)/2;i>=0;i--){   
            //k save the node being judged    
            int k=i;    
            //If the child node of the current k node exists    
            while(k*2+1<=lastIndex){    
                //Index of left child node of k node    
                int biggerIndex=2*k+1;    
                //If biggerIndex is less than lastIndex, the right child node of the k node represented by biggerIndex+1 exists    
                if(biggerIndex<lastIndex){  
  
                    //If the value of the right child node is large    
                    if(data[biggerIndex]<data[biggerIndex+1]){  
                          //biggerIndex always records the index of the larger child node    
                        biggerIndex++;    
                    }    
                }    
                //If the value of the k node is less than the value of its larger child node   
                if(data[k]<data[biggerIndex]){    
                    //Exchange them    
                    swap(data,k,biggerIndex);    
                    //Assign the biggerIndex to k, start the next cycle of the while cycle, and re ensure that the value of the k node is greater than the value of its left and right child nodes    
                    k=biggerIndex;    
                }else{    
                    break;    
                }    
            }    
        }    
    }  
}

1.3 exchange sorting

1.3.1 bubble sorting

1.3.1.1 definition

Bubble Sort is a simple exchange algorithm. It repeatedly visits the sequence to be sorted, compares two elements at a time, and exchanges them if they are in the wrong order. The work of visiting the sequence is repeated until there is no need to exchange, that is, the sequence has been sorted. The name of this algorithm comes from the fact that smaller elements will slowly "float" to the top of the sequence through exchange.

The operation of bubble sorting algorithm is as follows:

  1. Compare adjacent elements. If the first one is bigger than the second, exchange them.
  2. Do the same for each pair of adjacent elements, from the first pair at the beginning to the last pair at the end. At this point, the last element should be the largest number.
  3. Repeat the above steps for all elements except the last one.
  4. Continue to repeat the above steps for fewer and fewer elements at a time until no pair of numbers need to be compared

Basic idea: in a group of numbers to be sorted, compare and adjust the two adjacent numbers from top to bottom for all the numbers within the range that have not been sorted, so that the larger number sinks and the smaller number rises. That is, whenever two adjacent numbers are compared and their sorting requirements are found to be opposite, they will be exchanged

As shown in the figure:

1.3.1.2 java implementation

public class bubbleSort {  
public  bubbleSort(){  
     int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};  
    int temp=0;  
    for(int i=0;i<a.length-1;i++){  
        for(int j=0;j<a.length-1-i;j++){  
        if(a[j]>a[j+1]){  
            temp=a[j];  
            a[j]=a[j+1];  
            a[j+1]=temp;  
        }  
        }  
    }  
    for(int i=0;i<a.length;i++)  
        System.out.println(a[i]);     
}  
}  

1.3.2 quick sort

1.3.2.1 definition

Quick sort may feel fast after hearing the name, but the worst case of algorithm time complexity is the same as insertion sort. The reason why it becomes quick sort is that its average efficiency is faster than heap sort. Quick sort is also based on the idea of divide and conquer, which is similar to merge sort, but quick sort is the original address, and it does not need to open up new storage space to operate directly in the original array. The idea of quick sort is very simple. Select a keyword K to divide the original array into two parts, g1 and g2. All elements in g1 are smaller or equal than k, while all data in g2 are larger or equal than K. in this way, we can quickly sort g1 and g2 respectively, and finally we get an ordered array.

Basic idea: select a reference element, usually the first element or the last element. Through one scan, the sequence to be arranged is divided into two parts. One part is smaller than the reference element and one part is greater than or equal to the reference element. At this time, the reference element is in the correct position after it is arranged, and then recursively sort the divided two parts in the same way
As shown in the figure:

The method is actually very simple: start "detection" from both ends of the initial sequence "6 1 2 7 9 3 4 5 10 8". First find a number less than 6 from right to left, then find a number greater than 6 from left to right, and then exchange them. Here, you can use two variables I and j to point to the leftmost and rightmost of the sequence, respectively. Let's give these two variables nice names "sentry I" and "sentry J". At the beginning, let sentry I point to the leftmost side of the sequence (i.e. i=1) and point to the number 6. Let sentinel J point to the rightmost side of the sequence (i.e. = 10) and point to the number

1.3.2.2 java implementation

public class quickSort {  
  public static void main(String[] args) {
        int a[] = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51};
        if (a.length > 0) {    //Check whether the array is empty
            _quickSort(a, 0, a.length - 1);
        }
        System.out.println(Arrays.toString(a));
    }
    public static void _quickSort(int[] list, int low, int high) {
        if (low < high) {
            int middle = getMiddle(list, low, high);  //Split the list array into two
            _quickSort(list, low, middle - 1);        //Recursively sort low word list
            _quickSort(list, middle + 1, high);       //Recursively sort the high word list
        }
    }

    public static int getMiddle(int[] list, int low, int high) {
        int tmp = list[low];    //The first of the array is the central axis
        while (low < high) {
            while (low < high && list[high] >= tmp) {
                high--;
            }
            list[low] = list[high];   //Records smaller than the central axis move to the low end
            while (low < high && list[low] <= tmp) {
                low++;
            }
            list[high] = list[low];   //Records larger than the central axis are moved to the high end
        }
        list[low] = tmp;              //Center axis to tail
        return low;                   //Returns the position of the center axis
    }
}

Or as follows:

	@Test
    public void testQuickDemo(){
        int a[] = {49, 38, 65, 97, 76, 13, 27, 1};
        sort(a, 0, a.length - 1);
        System.out.println(Arrays.toString(a));
    }

    public void sort(int[] map, int start, int end) {
        if (start < end) {
            System.out.println("start"+Arrays.toString(map));
            int p = getPlocation(map, start, end);
            System.out.println("p====="+p);
            sort(map, start, p - 1);
            sort(map, p + 1, end);
            System.out.println("end"+Arrays.toString(map));
        }
    }
    public int getPlocation(int[] map, int start, int end) {
        int core = map[end];
        int i = start - 1;
        for (int j = start; j <= end - 1; j++) {
            if (map[j] <= core) {
                i++;
                int cache = map[j];
                map[j] = map[i];
                map[i] = cache;
            }
        }
        i++;
        map[end] = map[i];
        map[i] = core;
        return i;
    }

1.4 merge sort

1.4.1 definition

Basic sorting: Merge sorting method is to combine two (or more) ordered tables into a new ordered table, that is, the sequence to be sorted is divided into several subsequences, and each subsequence is ordered. Then the ordered subsequences are combined into an overall ordered sequence
As shown in the figure:

1.4.2 java implementation

import java.util.Arrays;  
  
public class MergeSortDemo{  
int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,56,17,18,23,34,15,35,25,53,51};  
public  mergingSort(){  
    sort(a,0,a.length-1);  
    for(int i=0;i<a.length;i++)  
        System.out.println(a[i]);  
}  
public void sort(int[] data, int left, int right) {  
    // TODO Auto-generated method stub  
    if(left<right){  
        //Find intermediate index  
        int center=(left+right)/2;  
        //Recursion on the left array  
        sort(data,left,center);  
        //Recursion on the right array  
        sort(data,center+1,right);  
        //merge  
        merge(data,left,center,right);            
    }  
}  
public void merge(int[] data, int left, int center, int right) {  
    // TODO Auto-generated method stub  
    int [] tmpArr=new int[data.length];  
    int mid=center+1;  
    //Index of the middle array of third records  
    int third=left;  
    int tmp=left;  
    while(left<=center&&mid<=right){  
        //Take the smallest one from the two arrays and put it into the middle array  
        if(data[left]<=data[mid]){  
            tmpArr[third++]=data[left++];  
        }else{  
            tmpArr[third++]=data[mid++];  
        }  
    }  
    //The rest is put into the middle array in turn  
    while(mid<=right){  
        tmpArr[third++]=data[mid++];  
    }  
    while(left<=center){  
        tmpArr[third++]=data[left++];  
    }  
    //Copy the contents of the middle array back to the original array  
    while(tmp<=right){  
        data[tmp]=tmpArr[tmp++];  
    }  
    System.out.println(Arrays.toString(data));  
}  
  
} 

1.5 cardinality sorting

1.5.1 definition

Basic idea: unify all values to be compared (positive integers) into the same digit length, and fill zero in front of the shorter digit. Then, start from the lowest order and sort once in turn. In this way, from the lowest order to the highest order, the sequence becomes an ordered sequence
As shown in the figure:

1.5.2 java implementation

import java.util.ArrayList;  
  
import java.util.List;         
public class radixSort {    
         int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,101,56,17,18,23,34,15,35,25,53,51};  
  
public radixSort(){    
         sort(a);    
         for(int i=0;i<a.length;i++)    
                   System.out.println(a[i]);    
}  
  
public  void sort(int[] array){                               
        //First, determine the number of sortings;       
        int max=array[0];       
        for(int i=1;i<array.length;i++){       
                    if(array[i]>max){      
               max=array[i];       
                    }       
                 }                               
        int time=0;       
         //Judgment digit;       
                 while(max>0){       
                    max/=10;       
                     time++;       
                 }                               
        //Establish 10 queues;       
                 List<ArrayList> queue=new ArrayList<ArrayList>();       
                 for(int i=0;i<10;i++){       
                          ArrayList<Integer> queue1=new ArrayList<Integer>();     
                     queue.add(queue1);       
        }                              
                         //Conduct secondary distribution and collection;     
                 for(int i=0;i<time;i++){                                 
                     //Allocate array elements;       
                    for(int j=0;j<array.length;j++){       
                         //Get the time + 1st digit of the number;     
                             int x=array[j]%(int)Math.pow(10, i+1)/(int)Math.pow(10, i);   
                             ArrayList<Integer> queue2=queue.get(x);   
                             queue2.add(array[j]);   
                             queue.set(x, queue2);    
            }     
                      int count=0;//Element counter;       
            //Collect queue elements;       
                     for(int k=0;k<10;k++){     
                while(queue.get(k).size()>0){    
                         ArrayList<Integer> queue3=queue.get(k);    
                             array[count]=queue3.get(0);       
                             queue3.remove(0);    
                    count++;    
              }       
            }       
         }     
    }      
} 

The following is the time-consuming comparison diagram of the classical sorting algorithm running on my machine (the length of the random array used for the test is 50000), and the diagram of the test cases directly cut

Topics: Algorithm data structure