Java快速排序的两种思路方法

个人觉得快速排序挺难理解的,但是效率确实很高,也很实用,相信大家也想看看别人是如何写速排序的代码,以下就是我的代码,思路都在注释里了,有什么不解可以评论区沟通交流。

import java.util.Arrays;

public class QuickSortTest {
    public static void main(String[] args) {
        int[] arr = {9, 7, 5, 3, 1};
        System.out.println(Arrays.toString(arr));
        quickSort(arr, 0,arr.length-1 );
        System.out.println(Arrays.toString(arr));

//        System.out.println(Arrays.toString(arr));
//        quickSort2(arr, 0,arr.length-1 );
//        System.out.println(Arrays.toString(arr));

        int[] arrs = new int[80000];
        for (int i = 0; i < arrs.length; i++) {
            arrs[i] = (int) (Math.random() * 800000);
        }
        long l = System.currentTimeMillis();
        quickSort2(arrs, 0, arrs.length - 1);
        long l1 = System.currentTimeMillis();
        System.out.println("耗时为 "+ (l1 - l) +" 毫秒");
        System.out.println(arrs.length);
        System.out.println(Arrays.toString(arrs));
    }

    public static void quickSort(int[] arr, int left, int right) {
        //该方法是以中间值为标准数
        int l = left; //左指针
        int r = right; //右指针
        int poivt = arr[(left + right) / 2]; //中轴的值
        int temp;//临时变量,作为交换时使用
        while (l < r) {
            if (arr[l] < poivt) {//在pivot的左边一直找,找到大于等于pivot值,才退出
                l++;
            }
            if (arr[r] > poivt) {//在pivot的右边一直找,找到小于等于pivot值,才退出
                r--;
            }
            //如果l >= r说明pivot 的左右两的值,已经按照左边全部是
            //小于等于pivot值,右边全部是大于等于pivot值
            if (l == r) {
                break;
            }
            //交换位置
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            //如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
            //如果r--不理解也可以换成l++,l后移,但是效率会略微降低
            if (arr[l] == poivt) {
                r--;
            }
            //如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
            //同理也可以换成r--
            if (arr[r] == poivt) {
                l++;
            }
        }
        if (l == r) { //如果 l == r, 必须l++, r--, 否则为出现栈溢出
            l++;
            r--;
        }
        if (left < r) {//向左递归
            quickSort(arr, left, r);
        }
        if (right > l) {//向右递归
            quickSort(arr, l, right);
        }
    }

    public static void quickSort2(int[] arr, int start, int end) {
        //该方法是以第一个值为标准数
        //如果开始位置和结束位置重合,实际上就是一个数字,所以开始位置一定要比结束位置小,而且不能相等
        if (start < end) {
            //设定标准数,也就是快速排序的过程中,和标准数进行比较,通常用第一个数字即可
            //注意这里用的是arr[start],按说在第一次的时候是0,应该写成arr[0],但是不可以
            //因为快速排序是一个递归的操作,第二次进来的时候,就不是arr[0]了
            int stand = arr[start];
            //开始找开始位置和结束位置
            //我们知道快速排序其实就是有一个开始位置和一个结束位置,当开始位置比选定的标准数字大的时候,就会替换掉
            //结束位置的数字,这个时候结束位置的下标开始向前移动,然后如果结束位置的数字比标准数字,则替换开始位置的数字
            //在循环的过程中如果开始位置/结束位置的数字 不比标准数字大或者小,这个时候开始位置和结束位置就会向后/向前移动

            //开始位置
            int low = start;
            //结束位置
            int high = end;

            while (low < high) {
                //这个时候我们已经找定了开始位置和结束位置
                //第一次是要拿高位和低位进行比较,如果高位比标准数字大,则高位则向前移动一位
                while (low < high && arr[high] >= stand) {
                    high--;
                }
                //当然了并不是所有高位数字都比低位大,如果比低位要小,则这个数字要覆盖低位的数字
                arr[low] = arr[high];

                //然后这个时候低位开始移动,如果低位比标准数字小,则低位的下标向后移动一位
                while (low < high && arr[low] <= stand) {
                    low++;
                }

                //当然了并不是所有时候低位都比标准数字要小,如果比标准数字大的话,这个时候就要替换掉高位的数字
                arr[high] = arr[low];
            }

            //到了这一步就会出现一个情况,低位和高位相同,那么这个位置就用标准数字去替换
            //这里low和high实际上是相同的数字,所以写哪个都无所谓
            arr[low] = stand;

            //然后第一轮排序完毕,我们就会发现以标准数字为分界线,我们有两个序列了,这个时候,我们就调用递归来分别对两个序列进行排序
            //先做低位递归
            quickSort2(arr, start, low - 1);
            //然后再做高位递归
            quickSort2(arr, low + 1, end);
        }
    }
}

这是打印的结果图
在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值