Quick sort
basic thought
Quicksort is an improvement on bubble sort. The basic idea is: through one-time sorting, the data to be sorted is divided into two independent parts. All the data in one part is smaller than all the data in the other part, and then the two parts of data are sorted quickly according to this method. The whole sorting process can be recursive, so that the whole data becomes an ordered sequence
Number of excavation and filling + divide and conquer method
graphic
Solution steps
Quick sort uses divide and conquer strategy to divide a sequence into two subsequences. The basic steps are as follows:
-
First, take a number from the sequence as the reference number;
-
Partition process: put all the large numbers to its right, and all the numbers less than or equal to it to its left;
-
Step 2 is performed recursively on the left and right subsequences until there is only one number in each interval.
Taking an array as an example, take the first number of the interval as the benchmark number.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
72 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 48 | 85 |
-
Initially, i = 0; j = 9; temp = a[i] = 72
Since the number in a[0] has been saved to temp, it can be understood as digging a hole in array a[0] and filling it with other data.
-
Start with j and move forward to find a number smaller than or equal to temp. When j = 8, meet the conditions, dig out a[8] and fill it into the previous pit a[0].
a[0] = a[8]; i++; Such a pit a [0] is solved, but a new pit a [8] is formed. What should we do? Easy, find the number to fill a[8] this hole.
-
This time, find a number greater than temp from i. When i = 3, if it meets the conditions, dig out a[3] and fill it into the previous pit, a[8] = a[3]; j--;
The array becomes:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
48 | 6 | 57 | 88 | 60 | 42 | 83 | 73 | 88 | 85 |
i = 3; j = 7; temp = 72
Repeat the above steps, first from the back to the front, and then from the front to the back.
Look forward from j, when j = 5, meet the conditions, dig out a[5] and fill it into the previous pit, a[3] = a[5]; i++;
Start from i and look back. When i = 5, exit because i==j.
At this time, i = j = 5, and a[5] is just the pit dug last time, so fill temp into a[5].
The array becomes:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
---|---|---|---|---|---|---|---|---|---|
48 | 6 | 57 | 42 | 60 | 72 | 83 | 73 | 88 | 85 |
It can be seen that the numbers before a[5] are smaller than it, and the numbers after a[5] are larger than it. Therefore, repeat the above steps for the two sub intervals a[0... 4] and a[6... 9].
Summarize the number of excavation and filling
1.i = L; j = R; Dig out the reference number to form the first pit a[i].
2. j -- find the number smaller than it from back to front, dig out the number and fill it in the previous pit a[i].
3. i + + find a number larger than it from front to back. After finding it, dig out the number and fill it into the previous pit a[j].
4. Repeat steps 2 and 3 until i==j, and fill the benchmark number in a[i].
The benchmark number shall be taken as the middle of three numbers
code implementation
public class Test09 { private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } private static void printArr(int[] arr) { for (int anArr : arr) { System.out.print(anArr + " "); } } private static int partition(int[] arr, int left, int right) { // Three number median segmentation method is adopted //-------------------------------------- int mid = left + (right - left) / 2; // Make sure the left end is small if (arr[left] > arr[right]) swap(arr, left, right); // Ensure that the middle is small if (arr[mid] > arr[right]) swap(arr, mid, right); // Ensure the minimum in the middle and the maximum in the left and right if (arr[mid] > arr[left]) swap(arr, left, mid); //-------------------------------------- int pivot = arr[left]; while (right > left) { // Judge the benchmark number first and compare the following numbers in turn // Find a number smaller than the reference number from back to front while (pivot <= arr[right] && left < right) { --right; } // When the reference number is greater than arr[right], fill the pit. // Put the number smaller than the reference number in the reference number position, and fill the number of right in the left position //The array is divided into two sequences with the benchmark number as the boundary, which are larger and smaller than the benchmark number respectively if (left < right) { arr[left] = arr[right]; ++left; } // Now it's arr[right] time to fill the pit while (pivot >= arr[left] && left < right) { ++left; } if (left < right) { arr[right] = arr[left]; --right; } } arr[left] = pivot; return left; } private static void quickSort(int[] arr, int left, int right) { if (arr == null || left >= right || arr.length <= 1) return; int mid = partition(arr, left, right); quickSort(arr, left, mid); quickSort(arr, mid + 1, right); } public static void main(String[] args) { int[] arr = {6, 4, 3, 2, 7, 9, 1, 8, 5}; quickSort(arr, 0, arr.length - 1); printArr(arr); } }