6-5 quick sort

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:

  1. First, take a number from the sequence as the reference number;

  2. Partition process: put all the large numbers to its right, and all the numbers less than or equal to it to its left;

  3. 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
  1. 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.

  2. 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.

  3. 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);
    }
}

Posted by cheechm on Tue, 23 Nov 2021 11:33:43 -0800