快速排序

快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

关键部分:

  • 被某个数,分割为两部分,其中一部分比分割数小,另外一部分比分割数大
  • 不断的进行分割,满足上面的性质,直到不可再分为止

根据上面的思想,画了图:

  • 每次都随机找一个数
  • 然后按照被找到的数进行分割

编码

  1. 随机找一个数
        int randomIndex = new Random().nextInt(end - start) + start;
        int splitNumber = nums[randomIndex];
        System.out.println(
                String.format("当前start:%d, end:%d,选取的Index为:%d , 数字为:%d" ,start,end, randomIndex,splitNumber)
        );

复制代码
  1. 根据分割数进行排序
        int gt = end;
        int lt = start;
        // 新开辟一个数组区间
	int[] tmp = new int[nums.length];
        for (int i = start; i <= end; i++) {
            // 比分割数大的都放在数组后面
            if (nums[i] > splitNumber){
                tmp[gt] = nums[i];
                gt--;
            // 比分割数小的都放在数组前面    
            }else if (nums[i] < splitNumber){
                tmp[lt] = nums[i];
                lt++;
            }
        }
		
	 	// 在分割数的位置给分割数赋值
        for (int i = lt; i <= gt; i++) {
            tmp[i] = splitNumber;
        }
复制代码
  1. 将数字赋值到原本的数组
    for (int i = start; i <= end; i++) {
            nums[i] = tmp[i];    
       }
复制代码
  1. 对剩下的两部分,再次分割
		// 分割左面的
        quickSort(nums,start,lt-1);
		// 分割右面的
        quickSort(nums,gt+1,end);
复制代码
  1. 完整代码
    static void quickSort(int[] nums){
        quickSort(nums,0,nums.length - 1);
    }
    
        private static void quickSort(int[] nums, int start, int end) {
        if (end <= start
                ){
            return;
        }

        int gt = end;
        int lt = start;

        int randomIndex = new Random().nextInt(end - start) + start;
        int splitNumber = nums[randomIndex];
        System.out.println(
                String.format("当前start:%d, end:%d,选取的Index为:%d , 数字为:%d" ,start,end, randomIndex,splitNumber));

        int[] tmp = new int[nums.length];
        for (int i = start; i <= end; i++) {
            if (nums[i] > splitNumber){
                tmp[gt] = nums[i];
                gt--;
            }else if (nums[i] < splitNumber){
                tmp[lt] = nums[i];
                lt++;
            }
        }

        for (int i = lt; i <= gt; i++) {
            tmp[i] = splitNumber;
        }

        System.out.println("临时数组:" + Arrays.toString(tmp));
        System.out.print(
                String.format("lt=%d,gt=%d,currentArr: ",lt,gt)

        );
        for (int i = start; i <= end; i++) {
            nums[i] = tmp[i];
            System.out.print(tmp[i]);
            System.out.print(",");
        }
        System.out.println("");

        quickSort(nums,start,lt-1);
        quickSort(nums,gt+1,end);

    }
复制代码

测试结果

额外

感觉上面的方式有点浪费空间,在分割数组的时候,如果不开辟新的数组应该也是可以的。尝试不分割数组的话

需要考虑:

  • 当前要比较的下标index,以及下标对应的元素currentNum
  • 存放大于index元素的下标gt , 存放小于index元素的下标lt

编码:

  1. 下标index,统一取为当前数组的第一个元素
        int randomIndex = start;
        int splitNumber = nums[randomIndex];
复制代码
  1. 进行数组处理,拆分为两部分
        int gt = end;
        int lt = start;
        for (int i = start; i <= end; i++) {
            // 以及处理完了
            if (gt == i){
                nums[lt] = splitNumber;
                break;
            }
			// 大的放gt那边,交换元素之后,记得不要让i的下标继续走
            if (nums[i] > splitNumber){
                Helper.swap(nums,i,gt);
                gt--;
                i--;
            // 小的放lt   
            }else if (nums[i] < splitNumber){
                nums[lt] = nums[i];
                lt++;
            }
        }
复制代码
  1. 重复上面的步骤
        quickSortNew(nums,start,lt);
        quickSortNew(nums,gt,end);
复制代码
  1. 完整代码
    private static void quickSortNew(int[] nums, int start, int end) {
        if (end <= start
                ){
            return;
        }

        int gt = end;
        int lt = start;

//        int randomIndex = new Random().nextInt(end - start) + start;
        int randomIndex = start;
        int splitNumber = nums[randomIndex];

        System.out.println(
                String.format("当前start:%d, end:%d,选取的Index为:%d , 数字为:%d" ,start,end, randomIndex,splitNumber));


        for (int i = start; i <= end; i++) {
            if (gt == i){
                nums[lt] = splitNumber;
                break;
            }

            if (nums[i] > splitNumber){
                Helper.swap(nums,i,gt);
                gt--;
                i--;
            }else if (nums[i] < splitNumber){
                nums[lt] = nums[i];
                lt++;
            }
        }

        System.out.println(
                String.format("lt=%d,gt=%d,currentArr:=%s ",lt,gt,Arrays.toString(nums))

        );


        quickSortNew(nums,start,lt);
        quickSortNew(nums,gt,end);

    }

复制代码
  1. 测试效果

最后

里面的打印信息为了调试,在地柜的时候,debug的方式感觉不如打印的方式直白,通过查看打印信息,一眼就看出来程序走到了哪一个步骤。

关于快速排序就到这了。

转载于:https://juejin.im/post/5c96f72c6fb9a070df166a52

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值