2, Java data structure and algorithm - sorting (explanation and code)

1, Simple sort

1.1 introduction to comparable interface

Compare elements, and Java provides an interface. Comparable is used to define sorting rules. Here we briefly review the comparable interface in the form of a case. (remember the customized sorting method corresponding to Comparator)

**Demand: * * 1 Define a Student class with age and name and username attributes, and provide comparison rules through the Comparable interface;
2. Define the Test class Test, and define the Test method Comparable getMax(Comparable c1,Comparable c2) in the Test class Test to complete the Test

The following shows some definitions of a Student class Student.

//1. Define a Student class with age and username attributes, and provide comparison rules through the Comparable interface;
public class Student implements Comparable<Student>{
    private String username;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "username='" + username + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public int compareTo(Student o) {
        return this.getAge()-o.getAge();
    }
}

Here are some test classes that define Comparable.

//2. Define the Test class Test, and define the Test method Comparable getMax(Comparable c1,Comparable c2) in the Test class Test to complete the Test
public class TestComparable {

    public static void main(String[] args) {
        //Create two Student objects and call the getMax method to complete the test
        Student s1 = new Student();
        s1.setUsername("Zhang San");
        s1.setAge(18);

        Student s2 = new Student();
        s2.setUsername("Li Si");
        s2.setAge(20);

        Comparable max = getMax(s1, s2);
        System.out.println(max);
    }

    public static Comparable getMax(Comparable c1,Comparable c2){
        int result = c1.compareTo(c2);
        //If result < 0, c1 is smaller than c2;
        //If result > 0, c1 is greater than c2;
        //If result==0, c1 is as large as c2;
        if (result>=0){
            return c1;
        }else{
            return c2;
        }
    }
}

1.2 bubble sorting

Bubble Sort is a relatively simple sorting algorithm in the field of computer science.
Sorting principle:

  1. Compare adjacent elements. If the previous element is larger than the latter, the positions of the two elements are exchanged.
  2. Do the same for each pair of adjacent elements, from the first pair of elements to the last pair of elements at the end. The element in the final position is the maximum value.

Requirements:
Before sorting: {4,5,6,3,2,1}
After sorting: {1,2,3,4,5,6}

Bubble sorting API design:

Here are some bubble sort codes that implement O(n^2).

public class Bubble {
    /*
       Sort the elements in array a
    */
    public static void sort(Comparable[] a){
        for(int i=a.length-1;i>0;i--){
            for(int j=0;j<i;j++){
                //{6,5,4,3,2,1}
                //Compare the values at index j and index j+1
                if (greater(a[j],a[j+1])){
                    exch(a,j,j+1);
                }
            }
        }
    }

    /*
        Compare whether the v element is larger than the w element
     */
    private static  boolean greater(Comparable v,Comparable w){
        return v.compareTo(w)>0;
    }

    /*
    Array elements i and j swap positions
     */
    private static void exch(Comparable[] a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i]=a[j];
        a[j]=temp;
    }
}

Some bubble sorting tests are shown below.

public class BubbleTest {
    public static void main(String[] args) {
        Integer[] arr = {4,5,6,3,2,1};
        Bubble.sort(arr);

        System.out.println(Arrays.toString(arr));//{1,2,3,4,5,6}
    }

}

Here are some array implementations of bubble sorting.

 public static void main(String[] args) {
        int[] arr = new int[]{4,5,6,3,2,1};

        //Bubble sorting
        for(int i = 0;i < arr.length - 1;i++){
            for (int j = 0;j < arr.length - i - 1;j++){
                if (arr[j] > arr[j + 1]){
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        for (int i = 0;i < arr.length;i++){
            System.out.print(arr[i] + "\t");
        }
}

1.3 selection and sorting

Selective sorting is a more simple and intuitive sorting method.

Sorting principle:
1. During each traversal, it is assumed that the element at the first index is the minimum value, which is compared with the values at other indexes in turn. If the value at the current index is greater than the value at some other index, it is assumed that the value derived from some other index is the minimum value, and finally the index where the minimum value is located can be found
2. Exchange the values at the first index and the index where the minimum value is located

Select Sorting API design:

Requirements:
Before sorting: {4,6,8,7,9,2,10,1}
After sorting: {1,2,4,5,7,8,9,10}

Here are some quick sort implementations O (n^2).

public class Selection {
    /*
       Sort the elements in array a
    */
    public static void sort(Comparable[] a){
        for(int i=0;i<a.length -1;i++){
            //Define a variable to record the index of the smallest element. By default, it is the location of the first element participating in the selection sorting
            int minIndex = i;
            for(int j=i+1;j<a.length;j++){
                //You need to compare the value at the minimum index minIndex with the value at the j index;
                if (greater(a[minIndex],a[j])){
                    minIndex=j;
                }
            }

            //Swap the value at index minIndex where the smallest element is located and the value at index i
            exch(a,i,minIndex);
        }
    }

    /*
        Compare whether the v element is larger than the w element
     */
    private static  boolean greater(Comparable v,Comparable w){
        return v.compareTo(w)>0;
    }

    /*
    Array elements i and j swap positions
     */
    private static void exch(Comparable[] a,int i,int j){
        Comparable temp;
        temp = a[i];
        a[i]=a[j];
        a[j]=temp;
    }
}

Here are some quick sort code tests.

public class SelectionTest {
    public static void main(String[] args) {
        //raw data
        Integer[] a = {4,6,8,7,9,2,10,1};
        Selection.sort(a);
        System.out.println(Arrays.toString(a));//{1,2,4,5,7,8,9,10}
    }
}

1.4 insert sort

Insertion sort is a simple, intuitive and stable sorting algorithm.

Sorting principle:
1. Divide all elements into two groups, sorted and unordered;
2. Find the first element in the unordered group and insert it into the sorted group;
3. Flashback traverses the sorted elements and compares them with the elements to be inserted in turn until an element less than or equal to the element to be inserted is found, then put the element to be inserted in this position and move the other elements one bit backward;

Insert sort API design:

The following shows some implementations of insertion sorting code, with time complexity O(n^2).

/*
1.Divide all elements into two groups, sorted and unordered;
2.Find the first element in the unordered group and insert it into the sorted group;
3.Flashback traverses the sorted elements and compares them with the elements to be inserted in turn until an element less than or equal to the element to be inserted is found
 Insert the element in this position, and the other elements move back one bit;
 */
public class InsertionSort {
    /*
    Sort the elements in array a
     */
    public static void sort(Comparable[] a){
        for (int i = 1; i < a.length; i++) {
            //The current element is a[i]. Compare it with the elements before I to find the elements smaller than a[i]
            for (int j = i; j > 0; j--) {
                if (greater(a[j - 1],a[j])){
                    exch(a,j - 1,j);
                }else {
                    //If the element is found, the loop ends
                    break;
                }
                
            }
            
        }


    }

    /*
    Compare whether element a is larger than element b

     */
    private static boolean greater(Comparable a, Comparable b){
        return a.compareTo(b) > 0;
    }

    /*
    Exchange position of array elements a and b
     */
    private static void exch(Comparable[] a, int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;

    }
}

Here are some tests for inserting sorting.

public class InsertionTest {
    public static void main(String[] args) {
        Integer[] array = {4,3,2,10,12,1,5,6};

        InsertionSort.sort(array);

        System.out.println(Arrays.toString(array));

    }
}

2, Advanced sorting

Basic sorting, including bubble sorting, selection sorting and insertion sorting, and their time complexity in the worst case is divided
Through analysis, it is found that it is O(N^2), and the square order is analyzed through our previous learning algorithm. We know that with the increase of input scale, the time cost will rise sharply, so these basic sorting methods can not deal with larger-scale problems. Next, we learn some advanced sorting algorithms to reduce the time complexity of the algorithm to the highest order power.

2.1 Hill sorting

Hill sort is a kind of insertion sort, also known as "reduced incremental sort", which is a more efficient improved version of insertion sort algorithm.

Sorting principle:
1. Select a growth amount h and group the data according to the growth amount h as the basis for data grouping;
2. Insert and sort each group of data divided into groups;
3. Reduce the growth to 1 at least, and repeat the second step.

Determination of growth h
For each fixed rule of the value of growth h, we adopt the following rules:

Some determinations of growth h are shown below.

int h=1
while(h<5){
	h=2h+1;//3,7
}
//At the end of the cycle, we can determine the maximum value of h;
h The reduction rules are:
	h=h/2

API design for Hill sorting:

Here are some code implementations of hill sorting.

/*
1.Select a growth amount h and group the data according to the growth amount h as the basis for data grouping;
2.Insert and sort each group of data divided into groups;
3.Reduce the growth to 1 and repeat the second step.
 */
public class ShellSort {
    /*
Sort the elements in array a
 */
    public static void sort(Comparable[] a){

        int N = a.length;
        int h = 1;
        //Determine the maximum value of h
        while (h < N/2){
            h = 2 * h + 1;
        }

        //When the increment h is less than 1, the sorting ends
        while (h >= 1){
            //Find the element to insert
            for (int i = h; i < N; i++) {
                //a[i] is the element to be inserted
                //Need to insert a[i] into a[i - h],a[i - 2h] in
                for (int j = i; j >= h ; j-=h) {
                    //At this time, the element to be inserted is a[j], which needs to be combined with a[j - h],a[j - 2h] For comparison, if a[j] is small, the position needs to be exchanged, otherwise it does not need to be exchanged
                    if (greater(a[j - h],a[j])){
                        exch(a,j - h,j);
                    }else {
                        break;
                    }

                }

            }
            h /=2;
        }



    }

    /*
    Compare whether element a is larger than element b

     */
    private static boolean greater(Comparable a, Comparable b){
        return a.compareTo(b) > 0;
    }

    /*
    Exchange position of array elements a and b
     */
    private static void exch(Comparable[] a, int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;

    }
}

Here are some Hill sort code implementation tests.

public class ShellTest {
    public static void main(String[] args) {
        Integer[] array = {9,1,2,5,7,4,8,6,3,5};
        ShellSort.sort(array);

        System.out.println(Arrays.toString(array));
    }
}

Time complexity analysis of Hill sort
There are many versions of the time complexity analysis of Hill sort on the Internet. Because the mathematical principles covered in it are only complex and cumbersome, in order to facilitate understanding, the post analysis method and insertion sort are compared to evaluate its performance. The test data reverse is used here_ Arr.txt file, which stores the reverse data from 100000 to 1. The test is completed according to this batch data. File Baidu cloud disk link: Link: https://pan.baidu.com/s/128RPUDuWuqMd5spBOfv5Nw
Extraction code: 1234
.

Some Hill sort and other sort performance comparison test codes are shown below.

public class PerformanceTest {
    //Call different test methods to complete the test
    public static void main(String[] args) throws Exception {
        //1. Create an ArrayList set and save the read integers
        ArrayList<Integer> arrayList = new ArrayList<>();

        //Create a cache read stream BufferedReader, read data, and store ArrayList
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("reverse_arr.txt"))));
        String line = null;
        while ((line = bufferedReader.readLine()) != null){
            //Line is a string. Convert line to Integer Store in collection
            int i = Integer.parseInt(line);
            arrayList.add(i);
        }

        //Turn off I/O flow
        bufferedReader.close();

        //3. Convert the ArrayList set into an array
        Integer[] a = new Integer[arrayList.size()];
        arrayList.toArray(a);

        //4. Call the test code to complete the test
//        testBubble(a);//46984 seconds!
//        testInsertion(a);// Nine seconds!
//        testMerge(a);//101 seconds!
        //testQuick(a);
        testSelection(a);//13600 seconds!

    }

    //Fake sort
    public static void testBubble(Integer[] a)  {
        //1. Time before acquisition
        long start = System.currentTimeMillis();

        //2. Execute algorithm code
        BubbleSort.sort(a);

        //3. Time after acquisition
        long end = System.currentTimeMillis();

        System.out.println("The time taken for bubble sorting is:" + (end - start) + "Seconds!");

    }

    //Insert sort
    public static void testInsertion(Integer[] a)  {
        //1. Time before acquisition
        long start = System.currentTimeMillis();

        //2. Execute algorithm code
       InsertionSort.sort(a);

        //3. Time after acquisition
        long end = System.currentTimeMillis();

        System.out.println("The time taken to insert a sort is:" + (end - start) + "Seconds!");

    }

    //Select sort
    public static void testSelection(Integer[] a)  {
        //1. Time before acquisition
        long start = System.currentTimeMillis();

        //2. Execute algorithm code
        SelectionSort.sort(a);

        //3. Time after acquisition
        long end = System.currentTimeMillis();

        System.out.println("The time taken to select a sort is:" + (end - start) + "Seconds!");

    }

    //Merge sort
    public static void testMerge(Integer[] a)  {
        //1. Time before acquisition
        long start = System.currentTimeMillis();

        //2. Execute algorithm code
        MergeSort.sort(a);

        //3. Time after acquisition
        long end = System.currentTimeMillis();

        System.out.println("The time taken to merge and sort is:" + (end - start) + "Seconds!");

    }

    //Quick sort
    public static void testQuick(Integer[] a)  {
        //1. Time before acquisition
        long start = System.currentTimeMillis();

        //2. Execute algorithm code
        QuickSort.sort(a);

        //3. Time after acquisition
        long end = System.currentTimeMillis();

        System.out.println("The time taken for quick sort is:" + (end - start) + "Seconds!");

    }
}

From the comparison test of the code, it can be found that the efficiency of Hill sort is much higher than that of insert sort when dealing with large quantities of data.

2.2 merge sort

2.2. 1 recursion

Definition: when defining a method, the method itself is called inside the method, which is called recursion

Function: it usually transforms a large and complex problem into a smaller problem similar to the original problem. The recursive strategy only needs a small number of programs to describe the multiple repeated calculations required in the problem-solving process, which greatly reduces the amount of code of the program.

Note: in recursion, you can't call yourself unlimited. You must have boundary conditions to end the recursion, because each recursive call will open up a new space in the stack memory and re execute the method. If the recursion level is too deep, it is easy to cause stack memory overflow.

Requirements: please define a method to calculate the factorial of N by recursion;

Here are some factorials of N using recursive completion.

// A code block
var foo = 'bar';
// An highlighted block
var foo = 'bar';

2.2. 2 merge sort

Merge sort is an effective sort algorithm based on merge operation. This algorithm is a very typical application of divide and conquer method. The ordered subsequences are combined 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.

Sorting principle:
1. Split a set of data into two subgroups with equal elements as far as possible, and continue to split each subgroup until the number of elements in each subgroup after splitting is 1.
2. Merge two adjacent subgroups into an ordered large group;
3. Repeat step 2 until there is only one group.

Merge and sort API design:

The following shows some merging and sorting code implementation, with time complexity O(nlogn).

/*
1.Split a set of data into two subgroups with equal elements as far as possible, and continue to split each subgroup until the number of elements in each subgroup is
1 until.
2.Merging two adjacent subgroups into an ordered large group;
3.Repeat step 2 until there is only one group.
 */
public class MergeSort {
    /*
    Auxiliary data required for merging
     */
    private static Comparable[] assist;


    /*
  Sort the elements in array a (call yourself recursively)
   */
    public static void sort(Comparable[] a){
        //1. Initialize auxiliary array
        assist = new Comparable[a.length];//Define that the length of the last sorted array is consistent with the length of the original array
        //2. Define a lo variable and hi variable to record the maximum index and minimum index in the array respectively
        int lo = 0;
        int hi = a.length - 1;
        //3. Call the sort overloaded method to sort the elements in array a from index lo to hi
        sort(a,lo,hi);

    }

    /*
    Sorts the elements in array a from index lo to index hi
     */
    private static void sort(Comparable[] a,int lo,int hi){
        //Assuming that the array length is 0, there is no need to sort (security check)
        if (hi <= lo){
            return;
        }
        int mid = (lo + hi) / 2;

        //Sorts the elements from index lo to index mid
        sort(a, lo, mid);

        //Sort the elements between index mid + 1 and hi
        sort(a, mid + 1, hi);

        //merge the above two subgroups of lo
        merge(a,lo, mid,hi);



    }

    /*
    From index lo to index mid is a subgroup, and from index mid+1 to index hi is another subgroup,
    Merge the data of the two subgroups in array a into an ordered large group (from index lo to hi)
     */
    private static void merge(Comparable[] a,int lo,int mid,int hi){
        //Merge the data from lo to mid and mid+1 to hi into the index corresponding to the auxiliary array assist
        int i = lo;//Define a pointer to the index in the assist array that starts filling data
        int p1 = lo;//Defines a pointer to the first element of the first set of data
        int p2 = mid + 1;//Defines a pointer to the first element of the second set of data

        //Compare the element sizes of the left and right subgroups, and fill the data into the assist array
        while (p1 <= mid && p2 <= hi){
            if (less(a[p1],a[p2])){
                assist[i++] = a[p1++];
            }else {
                assist[i++] = a[p2++];
            }
        }

        //After the above cycle, if one of the conditions P1 < = mid & & P2 < = hi is not satisfied, it means that the merging of the left group or the right group is completed
        //Continue to fill the unfilled data into the assist, and execute the following cycle according to the avoidance of the left and right subgroups

        while (p1 <= mid){
            assist[i++] = a[p1++];
        }
        while (p2 <= hi){
            assist[i++] = a[p2++];
        }

        //So far, the elements from lo to hi in the assit auxiliary array are ordered, and the data is copied to the corresponding index in the a array
        for (int index = lo; index <= hi; index++) {
            a[index] = assist[index];

        }

    }

    /*
    Compare whether element a is larger than element b

     */
    private static boolean less(Comparable a, Comparable b){
        return a.compareTo(b) < 0;
    }

    /*
    Exchange position of array elements a and b
     */
    private static void exch(Comparable[] a, int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;

    }
}

Some merge sort code implementation tests are shown below.

public class MergeTest {
    public static void main(String[] args) {
        Integer[] array = {4, 6, 8, 7, 9, 2, 10, 1,12};
        MergeSort.sort(array);

        System.out.println(Arrays.toString(array));
    }
}

Merge sort time complexity analysis:
Merge sort is the most typical example of divide and conquer. In the above algorithm, a[lo... hi] is sorted. First, it is divided into a[lo... Mid] and a[mid+1... hi], which are sorted separately through recursive calls, and finally the ordered sub arrays are merged into the final sorting result. The exit of this recursion is that if an array can no longer be divided into two sub arrays, merge will be performed to determine the size of the elements and sort them when merging.

Assuming that the number of elements is n, the number of splits using merge sort is log2(n), so there are log2(n) layers. The time complexity of the final merge sort is: log2(n)* 2^(log2(n))=log2(n)*n. according to the large o derivation rule, the base number is ignored, and the time complexity of the final merge sort is O(nlogn);

Performance comparison between merge sort and Hill sort: performance comparison similar to Hill sort

Here are some performance comparisons between merge sort and Hill sort.

// A code block
var foo = 'bar';
// An highlighted block
var foo = 'bar';

Disadvantages of merge sorting:
When calling the merge sort algorithm, you need to apply for additional array space assist, resulting in increased space complexity. It is a typical space for time operation. This problem can be ignored in Java program development, but in the process of embedded development, the merging and sorting algorithm should be used carefully.

2.3 quick sort

Quick sort is an improvement of bubble sort. Its basic idea is to divide the data to be sorted into two independent parts through one-time sorting. All the data in one part is smaller than all the data in the other part, and then quickly sort the two parts of data according to this method. The whole sorting process can be recursive, so that the whole data becomes an ordered sequence.

Sorting principle:
1. First, set a boundary value, and divide the array into left and right parts through the boundary value;
2. Put the data greater than or equal to the boundary value to the right of the array, and the data less than the boundary value to the left of the array. At this time, all elements in the left part are less than or equal to the boundary value, while all elements in the right part are greater than or equal to the boundary value;
3. Then, the data on the left and right can be sorted independently. For the array data on the left, you can take another boundary value and divide this part of the data into left and right parts. Similarly, place the smaller value on the left and the larger value on the right. The array data on the right can also be processed similarly.
4. By repeating the above process, it can be seen that this is a recursive definition. After the left part is sorted recursively, the right part is sorted recursively. When the data of the left and right parts are sorted, the sorting of the whole array is completed.

Quicksort API design:

Segmentation principle:
The basic idea of dividing an array into two subarrays:
1. Find a reference value and point to the head and tail of the array with two pointers respectively;
2. Search for an element smaller than the reference value from the tail to the head, stop the search, and record the position of the pointer;
3. Search for an element larger than the reference value from the head to the tail, stop the search, and record the position of the pointer;
4. Exchange the elements of the current left pointer position and the right pointer position;
5. Repeat steps 2, 3 and 4 until the value of the left pointer is greater than that of the right pointer.

Some quick sort code implementations are shown below.

/*
1.First, set a boundary value, and divide the array into left and right parts through the boundary value;
2.Put the data greater than or equal to the boundary value to the right of the array, and the data less than the boundary value to the left of the array. At this time, each element in the left part is less than
 Or equal to the boundary value, and all elements in the right part are greater than or equal to the boundary value;
 */
public class QuickSort {

    /*
    Compare whether element a is larger than element b

     */
    private static boolean less(Comparable a, Comparable b){
        return a.compareTo(b) < 0;
    }

    /*
    Exchange position of array elements a and b
     */
    private static void exch(Comparable[] a, int i,int j){
        Comparable temp;
        temp = a[i];
        a[i] = a[j];
        a[j] = temp;

    }

    /*
Sort the elements in array a
*/
    public static void sort(Comparable[] a){
        int lo = 0;
        int hi = a.length - 1;
        sort(a,lo,hi);


    }

    private static void sort(Comparable[] a,int lo,int hi){
        //Validate the array
        if (hi <= lo){
            return;
        }

        //Slice array a from lo to hi
        //The elements in the array from lo index to hi index need to be grouped
        int partition = partition(a, lo, hi);

        //Sort left progeny
        sort(a,lo,partition - 1);

        //Sort right subgroup
        sort(a,partition + 1,hi);
    }


    //For array a, from index lo to
    public static int partition(Comparable[] a,int lo,int hi){
        Comparable key = a[lo];//Take the element with index 0 as the base value
        int left = lo;//Define a left pointer, and the initial pointer points to the leftmost element
        int right = hi + 1;//Define a right pointer. The initial pointer points to the rightmost bit of the rightmost element

        //segmentation
        while (true){
            //Scan from right to left to find a value smaller than the reference value
            while (less(key,a[--right])){
                if (right == lo){
                    break;
                }
            }

            //Scan from left to right to find a value larger than the reference value
            while (less(a[++left],key)){
                if (left == hi){
                    break;
                }
            }

            if (left >= right){
                break;//End of scan
            }else {
                //Swap elements at left and right indexes
                exch(a,right,left);
            }

        }
        //Exchange the value at the index of the last rirht pointer and the index where the reference value is located
        exch(a,lo,right);
        return right;//Return right. This is the index value limit of the shard

    }

}

Here are some quick sort code implementation tests.

public class QuickTest {
    public static void main(String[] args) {
        Integer[] array = {4, 6, 8, 7, 9, 2, 10, 1,12,10};
        QuickSort.sort(array);

        System.out.println(Arrays.toString(array));
    }
}

Quick sort time complexity analysis:
The first segmentation of quick sort starts from both ends and searches alternately until left and right coincide. Therefore, the time complexity of the first segmentation algorithm is O(n), but the time complexity of the whole quick sort is related to the number of segmentation.
Optimal case: the benchmark number selected for each segmentation just divides the current sequence equally. In the optimal case, the time complexity of quick sorting is O(nlogn);

Worst case: the benchmark number selected for each segmentation is the maximum number or the minimum number in the current sequence, so that each segmentation will have a subgroup, so it will be segmented n times in total. Therefore, in the worst case, the time complexity of quick sorting is O(n^2);

Similarities and differences between quick sort and merge sort:
Quick sort is another divide and conquer sorting algorithm. It divides an array into two sub arrays and sorts the two parts independently. Quick sort and merge sort are complementary: merge sort divides the array into two sub arrays, sorts them respectively, and merges the ordered sub arrays to sort the whole array. The way of quick sort is that when the two arrays are ordered, the whole array is naturally ordered. In merge sort, an array is equally divided into two parts. The merge call occurs before processing the whole array. In quick sort, the position of the split array depends on the content of the array, and the recursive call occurs after processing the whole array.

2.4 stability of sorting

Definition of stability:
There are several elements in array arr, in which element A is equal to element B, and element A is in front of element B. If A sorting algorithm is used to sort, it can ensure that element A is still in front of element B, it can be said that the algorithm is stable.

Meaning of stability:
If a group of data only needs to be sorted once, the stability is generally meaningless. If a group of data needs to be sorted multiple times, the stability is meaningful. For example, the content to be sorted is a group of commodity objects. The first sorting is sorted by price from low to high, and the second sorting is sorted by sales volume from high to low. If the stability algorithm is used in the second sorting, objects with the same sales volume can still be displayed in the order of price, and only objects with different sales volumes need to be reordered. This can not only maintain the original meaning of the first sorting, but also reduce the system overhead.

Stability of common sorting algorithms:

Bubble sort:
Only when arr [i] > arr [i + 1], the positions of elements will be exchanged, and when they are equal, they will not be exchanged. Therefore, bubble sorting is a stable sorting algorithm.

Select sort:
Selective sorting is to select the smallest current element for each position, such as data {5 (1), 8, 5 (2), 2, 9}. The smallest element selected for the first time is 2, so 5 (1) will exchange positions with 2. At this time, when 5 (1) comes after 5 (2), the stability is destroyed. Therefore, selective sorting is an unstable sorting algorithm.

Insert sort:
The comparison starts from the end of the ordered sequence, that is, the element you want to insert is compared with the largest one that has been ordered. If it is larger than it, it is directly inserted behind it. Otherwise, look forward until you find its insertion position. If you encounter an element that is equal to the inserted element, put the element to be inserted after the equal element. Therefore, the sequence of equal elements has not changed. The order out of the original unordered sequence is the order after the order is arranged, so the insertion sort is stable.

Hill sort:
Hill sort is to insert and sort the elements according to the asynchronous length. Although one insertion sort is stable and will not change the relative order of the same elements, in different insertion sort processes, the same elements may move in their own insertion sort, and finally their stability will be disturbed. Therefore, Hill sort is unstable.

Merge sort:
Merge sort in the process of merging, the position will be exchanged only when arr [i] < arr [i + 1]. If the two elements are equal, the position will not be exchanged, so it will not destroy the stability. Merge sort is stable.

Quick sort:
Quick sort requires a benchmark value. Find an element smaller than the benchmark value on the right side of the benchmark value and an element larger than the benchmark value on the left side of the benchmark value, and then exchange the two elements. At this time, the stability will be destroyed. Therefore, quick sort is an unstable algorithm.

Keywords: Java Algorithm data structure IDE

Added by ssmK on Wed, 29 Dec 2021 10:27:23 +0200