Summary of Java implementation of various sorting algorithms for arrays

Keywords: Java Algorithm data structure

PS: the author is Xiaobai who is learning Java. Here we will summarize some knowledge related to Java (Java code implementation). If there are deficiencies, welcome to discuss and correct them. Thank you very much!!!

Summary of Java implementation of various sorting algorithms for arrays

0 sorting algorithm description

0.0 overview

Searching and sorting are the basic algorithms often used.

  • Search is relatively simple, no more than sequential search, binary search, hash table search, binary sort tree search.

  • Sorting is relatively more complex, because there are many sorting algorithms, and it is necessary to clarify the time complexity, space complexity, stability and other characteristics of each sorting algorithm, and select different sorting algorithms according to the situation.

The complexity of time and space is relatively simple, so I won't repeat it. Interested partners can study it specially!

Stability: in the record sequence to be sorted, there are multiple records with the same keyword. If they are sorted, the relative order of these records remains unchanged, that is, in the original sequence, S1=S2, and S1 is before S2, while in the sorted sequence, S1 is still before S2, then this sorting algorithm is said to be stable; Otherwise, it is called unstable.

Stability scenario: the scenario that needs to ensure stability is generally a complex object with multiple attributes, and the initialization order has a certain significance (for example, Student, before sorting, records from small to large according to Student id. after sorting by score, if two students have the same grades, the one with small Student id generally needs to be in front, not behind the one with large Student id), and so on, In this case, stability ranking makes sense.

Note: generally, stability is not considered when doing algorithm problems or numerical sorting.

0.1 comparison of sorting algorithms

The following is a comparison of various sorting algorithms, including average time complexity, fastest time complexity, slowest time complexity, space complexity and stability.

  • n is the data size
  • k is the number of barrels
Serial numberSorting algorithmAverage time complexityWorst time complexitySpatial complexityIs it stableApplication
1Bubble sorting O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)stablen smaller
2Select sort O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)instablen smaller
3Insert sort O ( n 2 ) O(n^2) O(n2) O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)stablen smaller
4Merge sort O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( n ) O(n) O(n)stablen larger
5Shell Sort O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( 1 ) O(1) O(1)instable
6Quick sort O ( n l o g n ) O(nlogn) O(nlogn) O ( n 2 ) O(n^2) O(n2) O ( l o g n ) O(logn) O(logn)instablen larger
7Heap sort O ( n l o g n ) O(nlogn) O(nlogn) O ( n l o g n ) O(nlogn) O(nlogn) O ( 1 ) O(1) O(1)instablen larger
8Count sort O ( n + k ) O(n+k) O(n+k) O ( n + k ) O(n+k) O(n+k) O ( k ) O(k) O(k)stable
9Bucket sorting O ( n + k ) O(n+k) O(n+k) O ( n 2 ) O(n^2) O(n2) O ( n + k ) O(n+k) O(n+k)stable
10Cardinality sort O ( n ∗ k ) O(n*k) O(n∗k) O ( n ∗ k ) O(n*k) O(n∗k) O ( n + k ) O(n+k) O(n+k)stable

Note: there are many quick sorting methods in general, because the ideas involved (the method partition of finding sentinels) can be applied to the variant problems related to sorting.

1 library sorting

In the Java toolkit, it provides a very easy way to sort arrays, that is A r r a y . S o r t ( ) Array.Sort() Array.Sort(), and its time and space efficiency are excellent (explained later).

in addition A r r a y . S o r t ( ) Array.Sort() Array.Sort() can sort not only arrays of basic data types, but also object arrays.

Here are several uses of it.

1.1 basic type array sorting

Sorting has two types: ascending and descending.

1. Ascending order

Basic type array sorting can be called directly A r r a y . S o r t ( ) Array.Sort() Array.Sort() (default ascending order)

public class JavaArraySort {
    /**
     * @param array: Description of data to be sorted: basic type, ascending by default
     */
    public static void sort1(int[] array) {
        System.out.println("Before ascending:");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();

        Arrays.sort(array);
        System.out.println("After ascending:");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }
    
    public static void main(String[] args) {
        int[] arrayInt = {3, 1, 5, 2, 6, 7, 9, 1};

        // Basic type - integer (same as floating point) - default ascending order
        sort1(arrayInt);
    }
}

Operation results:

Before ascending:
3 1 5 2 6 7 9 1 
After ascending:
1 1 2 3 5 6 7 9 

2. Descending order

There are three ways to realize the descending order of arrays. However, under these three ways, a prerequisite is that the array to be sorted cannot be the basic data type (for example, if the array to be sorted is int, it needs to be converted to Integer). These three methods and related codes are introduced below.

(1) Use official C o l l e c t i o n s . r e v e r s e O r d e r ( ) Collections.reverseOrder() Collections.reverseOrder().

(2) Implement the Comparator interface using an anonymous inner class.

(3) Create a class that implements the Comparator interface.

// Tool class of mode 3
public class MyIntegerComparator implements Comparator<Integer> {
    @Override
    public int compare(Integer o1, Integer o2) {
        return o2-o1;
    }
}

public class JavaArraySort {
    /**
     * @param array: Description of data to be sorted: basic type, descending
     */
    public static void sort2(Integer[] array) {
        System.out.println("Before descending:");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();

        // 1. Direct use of official
        Arrays.sort(array, Collections.reverseOrder());

        // 2. Use anonymous inner class to implement
        Arrays.sort(array, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        // 3. You can also create a class that implements the Comparator interface
        Arrays.sort(array, new MyIntegerComparator());

        System.out.println("After descending:");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }
    
    public static void main(String[] args) {
        // Note the array type here
        Integer[] arrayInteger = {3, 1, 5, 2, 6, 7, 9, 1};

        // Basic type - integer (like floating point) - descending
        sort2(arrayInteger);
    }
}

Operation results:

Before descending:
3 1 5 2 6 7 9 1 
After descending:
9 7 6 5 3 2 1 1 

1.2 sorting of object type array

There are two ways to sort object type arrays. The following is an example of the Student class (the attributes include id, name, and score).

  • The first is to let this class directly implement the comparable < T > interface and implement the interface method compareTo(). However, it is not recommended because it can only implement one sorting method (by id, name and score). If other situations are needed, the code needs to be changed, which is very inconvenient, and multiple sorting methods cannot be achieved.

  • The second is to create a class that implements the comparator < T > interface (the same as the third method in part 1.1) and implement the compare() method. This is recommended because it is easy to expand. Whenever there is a new sorting method, directly create a new class, implement the comparator < T > interface, and implement the specific sorting logic in the compare() method.

Student class

import org.jetbrains.annotations.NotNull;

public class Student implements Comparable<Student>{
    public int id;
    public String name;
    public int score;

    public Student(int id, String name, int score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }

    @Override
    public int compareTo(@NotNull Student o) {
        return Integer.compare(this.id, o.id);
    }
}

Sort by class StudentSortByScore

import java.util.Comparator;

public class StudentSortByScore implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.score - o2.score;
    }
}

Sorting using Arrays.sort

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;

public class JavaArraySort {
    /**
     * @param array Description of data to be sorted: object type, ascending order
     */
    public static void sort3(Student[] array) {
        System.out.println("Before ascending:");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();

        System.out.println("After ascending by student number:");
        // 1. Sorting of object types: the object class implements the comparable < T > interface and its method compareTo(), and changes the logic in ascending and descending order
        Arrays.sort(array);
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();

        // 2. (recommended) object type sorting: create a comparator < T > interface and implement its method compare(), and change the logic in ascending and descending order
        Arrays.sort(array, new StudentSortByScore());

        System.out.println("In ascending order:");
        for (int i = 0; i < array.length; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Student[] arrayStudent = {
                new Student(102, "Tom", 99),
                new Student(105, "Lucy", 80),
                new Student(100, "Jerry", 90),
                new Student(103, "Tony", 98)
        };
        // Object type (Student class) - ascending by Student number by default
        sort3(arrayStudent);
    }
}

Operation results

Before ascending:
Student{id=102, name='Tom', score=99} Student{id=105, name='Lucy', score=80} Student{id=100, name='Jerry', score=90} Student{id=103, name='Tony', score=98} 
After ascending by student number:
Student{id=100, name='Jerry', score=90} Student{id=102, name='Tom', score=99} Student{id=103, name='Tony', score=98} Student{id=105, name='Lucy', score=80} 
In ascending order:
Student{id=105, name='Lucy', score=80} Student{id=100, name='Jerry', score=90} Student{id=103, name='Tony', score=98} Student{id=102, name='Tom', score=99} 

1.3 underlying implementation principle of array.sort

A r r a y . S o r t ( ) Array.Sort() Array.Sort() has different implementations in different JDK versions, which are described below.

1. Different versions of Array.Sort

  • JDK6: quick sort is used for original types (int[],double[],char[],byte []), and merge sort is used for Object types (Object [])

  • JDK7: upgrade quick sort to double benchmark fast platoon (double benchmark fast platoon vs three-way fast platoon); Merge sort is upgraded to an improved version of TimSort

  • JDK8:, the Arrays.parallelSort() function is added to large sets. The fork join framework is used to make full use of multi-core. Large sets are segmented and then merged and sorted. In small continuous fragments, TimSort and DualPivotQuickSort are still used

2. TimSort

  • Algorithm content

    In order to reduce the backtracking of the ascending part and the performance retrogression of the descending part, the input is partitioned according to its ascending and descending characteristics. The input unit of sorting is not a single number, but a block partition. Each partition is called a run. For these run sequences, take one run at a time and merge them according to the rules. Each merge merges two runs into one run. The merged results are saved to the stack. Merge until all runs are consumed. At this time, merge the remaining runs on the stack until there is only one run left. At this time, the only run left is the result of sequencing.

  • Algorithm process

    • How to use bisection insertion sorting algorithm directly when the array length is less than a certain value (JDK1.8=32)
    • Find each run and merge it into the stack
    • Merge run by rule

3. Summary

  • A r r a y . S o r t ( ) Array.Sort() The underlying implementation of Array.Sort() selects different sorting algorithms to optimize according to the size of the array, so that the data can maintain a fast sorting speed under any circumstances.

2 bubble sorting

2.1 basic ideas

Bubble sorting is the most basic sorting method in sorting algorithm.

Repeatedly visit the element column to be sorted, compare two adjacent elements in turn, and exchange them if their order (e.g. from large to small) is wrong

2.2 algorithm process

Take ascending order (descending order only needs to change the size of the comparison) as an example. Two layers of loops are required:

(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. The last element is the maximum number.

(3) Repeat the above steps for all elements except the last one.

(4) Repeat steps (1), (2) and (3) above until no pair of numbers need to be compared. Note that fewer and fewer elements can be repeated each time (that is, the number of inner loops decreases as the number of outer loops increases, because one will be arranged at the end of the array at the end of each outer loop)

2.3 code implementation

public class BubbleSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        for (int i = 0; i < nums.length - 1; i++) { 
        	// Note the end condition of the inner loop, because every time the outer loop is performed, an ordered element (largest, second largest,...) will be added to the end of the array
            for (int j = 0; j < nums.length - 1 - i; j++) {
                if (nums[j] > nums[j + 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j + 1];
                    nums[j + 1] = temp;
                }
            }
        }
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

3 select sort

3.1 basic ideas

The bubble sorting is optimized by selecting sorting. Instead of exchanging during each traversal comparison, the minimum value of this traversal is recorded, and then the minimum value is moved to the beginning of this traversal after the traversal. Then, continue to find the smallest element from the remaining unordered elements and put it at the end of the sorted sequence.

In this way, although the comparison times have not changed, the number of exchanges is greatly reduced, and only N exchanges are required.

3.2 algorithm process

(1) First, find the smallest (large) element in the unordered sequence and store it at the beginning of the sorted sequence.

(2) Then continue to find the smallest (large) element from the remaining unordered elements, and then put it at the end of the sorted sequence.

(3) Repeat step 2 until all elements are sorted.

3.3 code implementation

public class SelectSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        for (int i = 0; i < nums.length - 1; i++) {
            // Record the index position of the smallest element
            int minIndex = i;
            for (int j = i + 1; j < nums.length; j++) {
                // Compare with the smallest element
                if (nums[minIndex] > nums[j]) {
                    minIndex = j;
                }
            }
            // Find the smallest element and exchange it
            int temp = nums[minIndex];
            nums[minIndex] = nums[i];
            nums[i] = temp;
        }
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

4 insert sort

4.1 basic ideas

Insert sorting is to build an ordered sequence. For unordered data, scan from back to front in the sorted sequence, find the corresponding position and insert. In the implementation of insertion sorting, in the process of scanning from back to front, it is necessary to repeatedly move the sorted elements back step by step to provide insertion space for the latest elements.

4.2 algorithm process

(1) Starting with the first element, the element can be considered to have been sorted

(2) Take out the next element and scan from back to forward in the sorted element sequence

(3) If the element (sorted) is larger than the new element, move the element to the next position

(4) Repeat step 3 until you find a location where the sorted element is less than or equal to the new element

(5) Insert the new element into the next location

(6) Repeat steps 2 to 5

4.3 code implementation

public class InsertSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        // The first element is sorted by default
        for (int i = 1; i < nums.length; i++) {
            // Current element to be sorted
            int current = nums[i];
            // Scan the previously sorted element column from the end
            int j = i - 1;
            while (j >= 0 && nums[j] > current) {
                // move backward 
                nums[j + 1] = nums[j];
                // Index forward
                j--;
            }
            // Insert current element into
            nums[j + 1] = current;
        }
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

5 merge sort

5.1 basic ideas

  • Merge sort is an effective sort algorithm based on merge operation. The algorithm is a very typical application of Divide and Conquer.

  • Merge sort is to merge the ordered subsequences to obtain a completely ordered sequence; In other words, order each subsequence first, and then order the subsequence segments. If two ordered tables are merged into one ordered table, it is called 2-way merging.

5.2 algorithm process

(1) The input sequence with length n is divided into two subsequences with length n/2;

(2) The two subsequences are sorted by merging;

(3) Merge two sorted subsequences into a final sorting sequence.

5.3 code implementation

Code in l e e t c o d e leetcode leetcode passed. l e e t c o d e leetcode leetcode sort link: Sort array

public class MergeSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        // Array length less than 2 is returned directly
        if (nums.length < 2) {
            return;
        }
        mergeSort(nums, 0, nums.length - 1);
    }

    public static void mergeSort(int[] nums, int left, int right) {
        // Recursive end condition
        if (left >= right) return;
        // Find the intermediate index. Be careful not to write it as (right + left) / 2. Overflow may occur
        int mid = left + (right - left) / 2;
        // Merge and sort the subsequences on the left (recursive)
        mergeSort(nums, left, mid);
        // Merge and sort the subsequences on the right (recursive)
        mergeSort(nums, mid + 1, right);
        // Merge left and right subsequences
        merge(nums, left, mid, right);
    }

    public static void merge(int[] nums, int left, int mid, int right) {
        // Merged array (pay attention to the array size setting)
        int[] mergeArray = new int[right - left + 1];

        // Index of the first element of the left subsequence
        int leftIndex = left;
        // Index of the first element of the right subsequence
        int rightIndex = mid + 1;

        // Index of the merged array
        int index = 0;

        while (leftIndex <= mid && rightIndex <= right) {
            //Take the smallest from the two arrays and put it into the temporary array
            if (nums[leftIndex] <= nums[rightIndex]) {
                mergeArray[index++] = nums[leftIndex++];
            } else {
                mergeArray[index++] = nums[rightIndex++];
            }
        }

        // Move the left subsequence or the remaining elements of the right subsequence into the merged array (only one loop will be executed at most)
        while (leftIndex <= mid) {
            mergeArray[index++] = nums[leftIndex++];
        }
        while (rightIndex <= right) {
            mergeArray[index++] = nums[rightIndex++];
        }

        // Copy the merged array elements to the original array
        for (int i = 0; i < mergeArray.length; i++) {
            nums[i + left] = mergeArray[i];
        }
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

6 hill sort

6.1 basic ideas

  • Hill sort is also an insert sort. It is an improved version of simple insert sort, also known as reduced incremental sort.

  • Hill sort is to group records by certain increment of subscript, and sort each group by direct insertion sort algorithm; As the increment decreases, each group contains more and more keywords. When the increment decreases to 1, the whole file is just divided into one group, and the algorithm terminates.

6.2 algorithm process

First, divide the whole record sequence to be sorted into several subsequences for direct insertion sorting. The specific algorithm description is as follows:

(1) Select an incremental sequence t 1 , t 2 , . . . , t k t_1,t_2,...,t_k t1, t2,..., tk, where t i > t j , t k = 1 t_i>t_j, t_k=1 ti​>tj​,tk​=1;

  • How to select an increment sequence: select an increment t 1 = l e n g t h / 2 t_1=length/2 t1 = length/2, continue in decreasing increments t = l e n g t h / 2 t=length/2 t=length/2, i.e. ${t_1, t_1-i*t,..., 1}, i=1,2,... $.

(2) Sort the sequence k times according to the number of incremental sequences k;

(3) Sort each trip according to the corresponding increment t 1 t_1 t1, divide the sequence to be arranged into several subsequences with length m, and directly insert and sort each sub table respectively. Only when the increment factor is 1, the whole sequence is treated as a table, and the table length is the length of the whole sequence.

6.3 code implementation

Code in l e e t c o d e leetcode leetcode passed. l e e t c o d e leetcode leetcode sort link: Sort array

public class ShellSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        int length = nums.length;
        // Increment start
        int gap = length >> 1;
        while (gap > 0) {
            for (int i = gap; i < length; i++) {
                // Record the last element of the group as the element to be sorted
                int temp = nums[i];
                // Find the previous element of the group
                int preIndex = i - gap;
                // Insert sort
                while (preIndex >= 0 && nums[preIndex] > temp) {
                    // If the previous element is greater than the latter, the exchange is performed (element moves back)
                    nums[preIndex + gap] = nums[preIndex];
                    // Continue looking for the previous element of the group
                    preIndex -= gap;
                }
                // Insert the element to be sorted into
                nums[preIndex + gap] = temp;
            }
            // Reduce increment
            gap >>= 1;
        }
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

7 quick sort

7.1 basic ideas

Randomly select a number in the array (the first element of the default array). In the array, those less than or equal to this number are placed on the left and those greater than this number are placed on the right. Then recursively call quick sorting on both sides of the array and repeat this process.

7.2 algorithm process

Quick sort uses divide and conquer to divide a list into two sub lists. The specific algorithm is described as follows:

(1) Pick out an element from the sequence, which is called "pivot";

(2) Reorder the sequence. All elements smaller than the benchmark value are placed in front of the benchmark, and all elements larger than the benchmark value are placed behind the benchmark (the same number can be on either side). After the partition exits, the benchmark is in the middle of the sequence. This is called a partition operation;

(3) Recursively sort subsequences that are smaller than the reference value element and subsequences that are larger than the reference value element.

7.3 code implementation

Code in l e e t c o d e leetcode leetcode passed. l e e t c o d e leetcode leetcode sort link: Sort array

public class QuickSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        int n = nums.length;
        quickSort(nums, 0, n - 1);
    }

    public static void quickSort(int[] nums, int low, int high) {
        if (low < high) {
            int pivot = partition(nums, low, high);
            quickSort(nums, low, pivot - 1);
            quickSort(nums, pivot + 1, high);
        }
    }

    static int partition(int[] nums, int low, int high) {
        int pivot = nums[low];
        while (low < high) {
            // Find a value smaller than sentinel from right to left
            while (low < high && nums[high] >= pivot) --high;
            nums[low] = nums[high];

            // Find a value greater than sentinel from left to right
            while (low < high && nums[low] <= pivot) ++low;
            nums[high] = nums[low];
        }
        // Change the position of the sentry
        nums[low] = pivot;
        // Return to the sentry's position
        return low;
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

8 heap sort

8.1 basic ideas

Heap sort is a sort algorithm designed by using heap data structure. Heap is a structure similar to a complete binary tree and satisfies the nature of heap: that is, the key value or index of a child node is always less than (or greater than) its parent node.

8.2 algorithm process

(1) The initial keyword sequence to be sorted { R 1 , R 2 , . . . , R n } \{R_1, R_2, ..., R_n\} {R1, R2,..., Rn} is constructed into a large top heap (the parent node is larger than the child node), which is the initial disordered area;

(2) Add heap top element R 1 R_1 R1 ^ with last element R n R_n Rn ^ exchange, and a new disordered region is obtained { R 1 , R 2 , . . . , R n − 1 } \{R_1, R_2, ..., R_{n-1}\} {R1, R2,..., Rn − 1} and new ordered regions { R n } \{R_n\} {Rn}, and ${R_1, R_2,..., r_ {n-1} < = R_ n $;

(3) Due to the new heap top after exchange R 1 R_1 R1} may violate the nature of the heap, so it is necessary to modify the current unordered area { R 1 , R 2 , . . . , R n − 1 } \{R_1, R_2, ..., R_{n-1}\} {R1, R2,..., Rn − 1} is adjusted to a new large top reactor, and then it is adjusted again R 1 R_1 R1 ^ exchange with the last element of the disordered region to obtain a new disordered region { R 1 , R 2 , . . . , R n − 2 } \{R_1, R_2, ..., R_{n-2}\} {R1, R2,..., Rn − 2} and new ordered regions { R n − 1 , R n } \{R_{n-1}, R_n\} {Rn−1​,Rn​} . Repeat this process until the number of elements in the ordered area is n-1, and the whole sorting process is completed.

8.3 code implementation

Code in l e e t c o d e leetcode leetcode passed. l e e t c o d e leetcode leetcode sort link: Sort array

public class HeapSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length <= 1) {
            return;
        }
        // Create a new maximum heap
        buildMaxHeap(nums);
        for (int i = nums.length - 1; i >= 1; i--) {
            // The top element is exchanged with the last element
            swap(nums, 0, i);
            // Adjust maximum heap
            adjustMaxHeap(nums, 0, i - 1);
        }
    }

    public static void buildMaxHeap(int[] nums) {
        // Build the maximum heap from the child node to the root node, and pay attention to the index relationship between the parent node and the child node (because it is replaced by an array, so child=parent*2, child=parent*2+1)
        for (int i = 1; i < nums.length; i++) {
            int parent = (i - 1) >> 1;
            int child = i;
            // When there are child nodes and the child node is larger than the parent node, the exchange is performed
            while (child > 0 && nums[parent] < nums[child]) {
                swap(nums, parent, child);
                // After the exchange, if the value of the parent node changes, it is necessary to judge the relationship between the parent node and the parent node of the parent node. In order to use the loop to realize this logic, update the indexes of the child and the parent node
                // The child node index is updated to the parent node index
                child = parent;
                // The parent node index is updated to the parent node index of the parent node
                parent = (parent - 1) >> 1;
            }
        }
    }

    public static void adjustMaxHeap(int[] nums, int parent, int last) {
        // If the root node value changes, you need to update the large top heap from the root node
        int left = 2 * parent + 1;
        int right = 2 * parent + 2;
        int maxIndex = left;
        // Find the largest child node. Note that the index cannot exceed the last index (that is, judge whether the parent node has children)
        if (right <= last && nums[right] > nums[left]) {
            maxIndex = right;
        }
        // Compare with the largest child node
        if (left <= last && nums[parent] < nums[maxIndex]) {
            // Swap to maximum child node
            swap(nums, parent, maxIndex);
            // Top down recursive updating of large top heap
            adjustMaxHeap(nums, maxIndex, last);
        }
    }

    public static void swap(int[] nums, int i, int j) {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

9 count sort

9.1 basic ideas

The core of counting sorting is to convert the input data values into keys and store them in the additional array space. As a sort with linear time complexity, count sort requires that the input data must be integers with a certain range.

Count sorting uses an additional array C, where the ith element is the number of elements with A value equal to i in the array A to be sorted. Then arrange the elements in A in the correct position according to array C. It can only sort positive integers.

Therefore, the limitations of count sorting: (1) the difference between the maximum and minimum elements of the array is very large, (2) count sorting cannot be used in these two cases when the element is not an integer.

However, it has its own usage scenarios: for example, sorting all employees of the company by age. (the age range of employees is basically 18-65, and they are all integers)

9.2 algorithm process

(1) Find the largest and smallest elements in the array to be sorted;

(2) Count the number of occurrences of each element with value i in the array and store it in item i of array C;

(3) All counts are accumulated (starting from the first element in C, and each item is added to the previous item);

(4) Reverse fill the target array: put each element i in the second row of the new array C i C_i Ci ¢ item, each element will C i C_i Ci minus 1.

9.3 code implementation

Code in l e e t c o d e leetcode leetcode passed. l e e t c o d e leetcode leetcode sort link: Sort array

public class CountSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        // Find the largest and smallest elements of the array
        int max = nums[0];
        int min = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > max)
                max = nums[i];
            if (nums[i] < min)
                min = nums[i];
        }
        // Count the occurrence times of each element and store it in item i of the data
        int[] countArray = new int[max - min + 1];
        for (int i = 0; i < nums.length; i++) {
            countArray[nums[i] - min]++;
        }

        // The statistical array is deformed, and the rear elements are equal to the sum of the front elements
        for (int i = 1; i < countArray.length; i++) {
            countArray[i] += countArray[i - 1];
        }

        // Traverse the original array in reverse order, find the correct position from the statistical array, and output it to the result array
        int[] sortedArray = new int[nums.length];
        for (int i = nums.length - 1; i >= 0; i--) {
            // Assign a value to the current position of sortedArray
            // Countarray [num [i] - min] - 1 represents how many elements are smaller than the num [i] value, so put num [i] in bit countarray [num [i] - min] - 1
            sortedArray[countArray[nums[i] - min] - 1] = nums[i];
            // The value given to the location of countArray is - 1
            countArray[nums[i] - min]--;
        }

        // Finally, it is filled into the original array,
        for (int i = 0; i < nums.length; i++) {
            nums[i] = sortedArray[i];
        }
    }


    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

10 barrel sorting

10.1 basic ideas

Bucket sorting is an upgraded version of counting sorting. It makes use of the mapping relationship of the function. The key to efficiency lies in the determination of the mapping function.

Working principle of bucket sorting: assuming that the input data obeys uniform distribution, divide the data into a limited number of buckets (uniform distribution results in almost the same number of bucket elements), and sort each bucket separately (it is possible to use another sorting algorithm or continue to use bucket sorting in a recursive manner)

10.2 algorithm process

(1) Manually set a bucket size as how many different values can be placed in each bucket (for example, when bucket size = = 5, the bucket can store {1,2,3,4,5} numbers, but the capacity is unlimited, that is, it can store 100 3200 2, etc.);

(2) Traverse the input data and put the data into the corresponding bucket one by one;

(3) To sort each bucket that is not empty, you can use other sorting methods or recursive bucket sorting;

(4) Splice the ordered data from a bucket that is not empty.

Note: if bucket sorting is used recursively to sort each bucket, when the bucket number is 1, manually reduce the bucket size and increase the number of buckets in the next cycle, otherwise it will fall into an endless loop, resulting in memory overflow.

10.3 code implementation

Code (slightly modified to meet the condition that the title input is an integer array, please refer to the modification of code main below) in l e e t c o d e leetcode leetcode passed. l e e t c o d e leetcode leetcode sort link: Sort array

import java.util.ArrayList;
import java.util.List;

public class BucketSort {
    public static List<Integer> sort(List<Integer> nums, int bucketSize) {
        if (nums == null || nums.size() < 2 || bucketSize < 1) {
            return nums;
        }
        int max = nums.get(0);
        int min = nums.get(0);
        // Max min found
        for (int i = 0; i < nums.size(); i++) {
            if (nums.get(i) > max)
                max = nums.get(i);
            if (nums.get(i) < min)
                min = nums.get(i);
        }
        // Set the number of buckets according to the size of the bucket
        int bucketCount = (max - min) / bucketSize + 1;
        // Create a new bucket collection and add all buckets to it
        List<List<Integer>> bucketArray = new ArrayList<>(bucketCount);
        for (int i = 0; i < bucketCount; i++) {
            bucketArray.add(new ArrayList<>());
        }

        // Add the array elements to be sorted to the corresponding bucket
        for (int i = 0; i < nums.size(); i++) {
            bucketArray.get((nums.get(i) - min) / bucketSize).add(nums.get(i));
        }

        // New array to save results
        List<Integer> resultArray = new ArrayList<>();

        // Sort each bucket in the bucket collection and add the sorted element to the result array
        for (int i = 0; i < bucketCount; i++) {
            List<Integer> everyBucket = bucketArray.get(i);
            if (everyBucket.size() > 0) {
                if (bucketCount == 1) {
                    bucketSize--;
                }
                // Other sorting methods can be used here, such as insert sorting
                // Here, bucket sorting is called recursively
                List<Integer> temp = sort(everyBucket, bucketSize);
                for (int j = 0; j < temp.size(); j++) {
                    // Merge data
                    resultArray.add(temp.get(j));
                }
            }
        }
        return resultArray;
    }

    public static void main(String[] args) {
        int[] numsArray = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] numsArray = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] numsArray = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] numsArray = {8};
        List<Integer> nums = new ArrayList<>();
        for (int i = 0; i < numsArray.length; i++) {
            nums.add(numsArray[i]);
        }
        
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.size(); i++) {
            System.out.print(nums.get(i) + " ");
        }
        System.out.println();

        List<Integer> result = sort(nums, 5);
        System.out.println("After sorting:");
        for (int i = 0; i < result.size(); i++) {
            System.out.print(result.get(i) + " ");
        }
        System.out.println();
    }
}

11 cardinality sorting

11.1 basic ideas

Cardinality sorting is sorting according to the low order, and then collecting; Then sort according to the high order, and then collect; And so on until the highest order. Sometimes some attributes are prioritized. They are sorted first by low priority and then by high priority. The final order is the high priority, the high priority, the same high priority, and the low priority, the high priority. Cardinality sorting is based on sorting separately and collecting separately, so it is stable.

Note: this method is only suitable for sorting positive integers. If you want to sort arrays with negative numbers, you need to optimize them. Some solutions are provided below

Solution 1:

  • Turn all elements into positive values (plus the opposite number of the smallest decimal point (note whether there is a negative number)). In addition, there is overflow in this case, so it needs to be stored in long (resulting in a larger space).
  • Then you can process it according to the following method to get the sorted array.
  • Finally, subtract the absolute value of the minimum value from all elements (also pay attention to judge whether there is a negative number).

Solution 2:

  • Expand the bucket size from 10 to 20, the negative number from small to large in bucket 0-9, and the positive number from small to large in bucket 10-19.

11.2 algorithm process

  • Get the maximum number in the array and get the number of bits k;
  • nums is the original array, and each bit is taken from the lowest bit to form a radius array;
  • Count and sort the radix (using the characteristics that count sorting is suitable for a small range of numbers);

11.3 code implementation

import java.util.ArrayList;
import java.util.List;

public class RadixSort {
    public static void sort(int[] nums) {
        if (nums == null || nums.length == 0) {
            return;
        }
        // Calculate the maximum number first
        int max = nums[0];
        for (int i = 1; i < nums.length; i++) {
            if (nums[i] > max) {
                max = nums[i];
            }
        }
        // Then calculate the number of digits of the maximum number
        int count = 0;
        while (max > 0) {
            max /= 10;
            count++;
        }

        // There are 0 ~ 9 10 numbers in total, and 10 list s are required for storage
        List<List<Integer>> bucketList = new ArrayList<>();
        for (int i = 0; i < 10; i++)
            bucketList.add(new ArrayList<>());

        int mod = 10, div = 1;
        // Cycle each bit of the number
        for (int i = 0; i < count; i++, mod *= 10, div *= 10) {
            // Loop each element in the array to be sorted and add the value corresponding to each bit to the corresponding list
            for (int j = 0; j < nums.length; j++) {
                // Get the value num corresponding to the element bit and put it in the list corresponding to num
                int num = (nums[j] % mod) / div;
                bucketList.get(num).add(nums[j]);
            }
            int index = 0;
            // sort
            for (int j = 0; j < bucketList.size(); j++) {
                for (int k = 0; k < bucketList.get(j).size(); k++)
                    nums[index++] = bucketList.get(j).get(k);
                // Pay attention to emptying to prevent adding elements next time
                bucketList.get(j).clear();
            }
        }
    }

    public static void main(String[] args) {
        int[] nums = {3, 1, 5, 2, 6, 7, 9, 1};
//        int[] nums = {1, 2, 3, 4, 5, 6, 7, 8};
//        int[] nums = {8, 7, 6, 5, 4, 3, 2, 1};
//        int[] nums = {8};
        System.out.println("Before sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();

        sort(nums);
        System.out.println("After sorting:");
        for (int i = 0; i < nums.length; i++) {
            System.out.print(nums[i] + " ");
        }
        System.out.println();
    }
}

summary

When doing algorithm problems and related contents, there are many contents related to sorting, so the contents of various sorting algorithms are summarized here for review later.

There are many contents, which inevitably have shortcomings. Welcome to discuss, exchange and correct. Thank you very much!!!

reference resources

  1. https://blog.csdn.net/yangzhongblog/article/details/8184707

  2. https://www.cnblogs.com/guoyaohua/p/8600214.html

  3. https://blog.csdn.net/cs_lwb/article/details/84556693

  4. leetcode boss heap problem solving

Posted by DexterMorgan on Sat, 25 Sep 2021 11:40:48 -0700