快速排序(萝卜填坑算法)【必会知识】

快速排序

  话说叫快排快排,但是在某种某件下会变成慢排,好了好了,进入正文

快排也是采用了一种分治的策略,该方法的基本思想是:

  • 1、先找一个基数,我一般用第一个数
  • 2、然后把比基数小的方左边,比基数大的方右边,然后以基数下边为分界线,划分左右区间
  • 3、然后左右区间进行重复的操作
  • 4、最后会得到 n 个有序的区间

直接举例子吧

现在有一个无序的数组 arr 👇
在这里插入图片描述

我们现在取第一个元素为基数 也就是 pivot=arr[0] = 77,left 下标为 0 ,right下标为 7 ,现在 下标为 0 的是一个萝卜坑等别人来填👇
在这里插入图片描述

现在从右边往左边扫描,找到第一个比pivot小的数,走走走,找到了,right = 6 的时候找到了,它比较倒霉哈哈,现在 arr[left++] = arr[right] ,好了现在萝卜坑被 arr[6] 填了 ,但是又出现了一个坑(arr[6])咋办?👇
在这里插入图片描述
照样填呗,刚刚是从右边扫描,现在从左边扫描,找到比基数pivot 大的数,看谁比较倒霉 ,走走走,欸,又找到了,arr[2] 这个小伙子太倒霉了,好了,现在按照老规矩,填坑 arr[right- -] = arr[left] ,现在右边的坑填上了,左边又有坑了,程序猿看了都绕道走。
在这里插入图片描述
继续呗,从右边扫描比pivot小的数,arr[5]不巧,中奖了,它要去填坑去了,arr[left++] =arr[right],👇
在这里插入图片描述
现在套路应该熟悉了,又从左边开始扫描比pivot大的数,不巧的是,left走到了坑为都没找到,现在只能把 pivot 往坑里丢了 👇
在这里插入图片描述
现在开始以 下标 5 为分界线 ,开始分区,做着与上面重复的操作。。。
分区:👇
在这里插入图片描述

代码演示

/**
 * 快速排序  100 W 条数据平均 0.143 S
 */
public class QuickSort {
    /**
     * 入口
     *
     * @param arr 待排序的数组
     */
    private static void quickSort(int[] arr) {
        quickSort(arr, 0, arr.length - 1);
    }

    /**
     * 重载
     *
     * @param arr        待排序的数组
     * @param startIndex 开始边界下标
     * @param endIndex   结束边界下标
     */
    private static void quickSort(int[] arr, int startIndex, int endIndex) {
        if (startIndex >= endIndex) { //递归结束条件
            return;
        }
        int pivotIndex = fillThePit(arr, startIndex, endIndex);
        quickSort(arr, startIndex, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, endIndex);
    }

    /**
     * 萝卜填坑
     *
     * @return 返回最后一个坑位的下标
     */
    private static int fillThePit(int[] arr, int startIndex, int endIndex) {
        int left = startIndex;
        int right = endIndex;
        int pivot = arr[startIndex];
        while (left < right) {
            while (left < right && arr[right] >= pivot) { // 从右向左找第一个小于pivot的数
                right--;
            }
            if (left < right) { //填坑,并生成新的坑arr[right]
                arr[left++] = arr[right];
            }
            while (left < right && arr[left] < pivot) { // 从左向右找第一个大于等于pivot的数
                left++;
            }
            if (left < right) { //填坑,并生成新的坑arr[left]
                arr[right--] = arr[left];
            }
        }
        //把基数填在最后一个没人管的坑里面
        arr[right] = pivot;
        return left;
    }

    public static void main(String[] args) {
        Random random = new Random();
        int[] arr = new int[1000000];
        for (int i = 0; i < 1000000; i++) {
            int num = random.nextInt(3000000);
            arr[i] = num;
        }
        long start = System.currentTimeMillis();
        quickSort(arr);
        long end = System.currentTimeMillis();
        System.out.println((end - start) / 1000.0);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值