快速排序

漫画:什么是快速排序?(完整版)_pivot

核心思想:二叉树插入元素一样,基准数就是根节点。

挖坑法

给定原始数列如下,要求从小到大排序:

image

首先,我们选定基准元素Pivot,并记住这个位置index,这个位置相当于一个“坑”。并且设置两个指针left和right,指向数列的最左和最右两个元素:

image

接下来,从right指针开始,把指针所指向的元素和基准元素做比较。如果比pivot大,则right指针向左移动;如果比pivot小,则把right所指向的元素填入坑中。

在当前数列中,1<4,所以把1填入基准元素所在位置,也就是坑的位置。这时候,元素1本来所在的位置成为了新的坑。同时,left向右移动一位。

image

此时,left左边绿色的区域代表着小于基准元素的区域。

接下来,我们切换到left指针进行比较。如果left指向的元素小于pivot,则left指针向右移动;如果元素大于pivot,则把left指向的元素填入坑中。

在当前数列中,7>4,所以把7填入index的位置。这时候元素7本来的位置成为了新的坑。同时,right向左移动一位。

image

此时,right右边橙色的区域代表着大于基准元素的区域。

下面按照刚才的思路继续排序:

8>4,元素位置不变,right左移

image

2<4,用2来填坑,left右移,切换到left。

image

6>4,用6来填坑,right左移,切换到right。

image

3<4,用3来填坑,left右移,切换到left。

image

5>4,用5来填坑,right右移。这时候left和right重合在了同一位置。

image

这时候,把之前的pivot元素,也就是4放到index的位置。此时数列左边的元素都小于4,数列右边的元素都大于4,这一轮交换终告结束。

java代码实现

package com.cy;

public class QuickSort {

    public static void main(String[] args) {
        int[] arr = { 5,2,4,9,7,66,44,55,76,345,67657,33,44,1,5,7,9,55,33 };
        sort(arr, 0, arr.length - 1);
    }
    public static void sort(int arr[], int low, int high) {
        int l = low;
        int h = high;
        int k = arr[low];
        while (l < h) {
            // 从后往前比较
            while (l < h && arr[h] >= k) { // 如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                h--;// h=6
            }
            if (l < h) {
                //拿到右边比标准值小的元素
                int temp = arr[h];
                //填充元素位置为标准值
                arr[h] = arr[l];
                //标准值位置为右边小的元素
                arr[l] = temp;
                //进行过一次替换后,没必要将替换后的两值再次比较,所以i++直接下一位与k对比
                l++;
            }
            // 从前往后比较
            while (l < h && arr[l] <= k) { // 如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                l++;
            }
            if (l < h) {
                //拿到左边比标准值大的元素
                int temp = arr[h];
                //填充元素位置为标准值
                arr[h] = arr[l];
                //标准值位置为左边大的元素
                arr[l] = temp;
                h--;
            }
            // 此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
        }
        print(arr);
        System.out.print("l=" + (l + 1) + "h=" + (h + 1) + "k=" + k + "\n");
        // 递归
        //l=h为标准值的位置
        if (l > low)//先判断l>low再次经行左边排序
            sort(arr, low, l - 1);// 左边序列。第一个索引位置到关键值索引-1
        if (h < high)//左边依次排序执行完递归后,弹栈进行右边排序
            sort(arr, l + 1, high);// 右边序列。从关键值索引+1到最后一个
    }
    // 打印数组的方法
    private static void print(int[] arr) {
        System.out.print("[");
        for (int i = 0; i < arr.length; i++) {
            if (i != (arr.length - 1)) {
                System.out.print(arr[i] + ",");
            } else {
                System.out.print(arr[i] + "]");
                System.out.println();
            }
        }
    }
}

你可能感兴趣的:(快速排序)