【算法详解】基于快排模板的一些分界点细节处理

本文讨论了dowhile循环的优势,解释了为何在快速排序中选择特定的循环条件,以及递归分界点的选择原则。特别关注了while(i 摘要由CSDN通过智能技术生成

1.为什么使用do while循环,而不用while循环:
   do while循环的好处在于,i和j会一直在更新,而不会因为在某种特殊的情况下,导致循环卡死。
  例如当arr[i] == arr[j] == x 时,i和j都不会更新,导致while进入了死循环当中。
   此案例也可以说明为什么会写成i = l - 1;和j = r + 1; 就是为了让i和j会一直在更新 ,适配do while循环所变化的
2.循环条件为什么是 arr[i]<x / arr[j]>x ,而不是 arr[i]<=x / arr[j]>=x.
   如果数组中的数值全都相同的话,do i++; while(arr[i] <= x);这个语句会一直执行,最后导致数组越界访问。这和另一种情况,所选数值x为整个数组中max一直,do i++; while(arr[i] <= x);此语句会一直执行,最后到数组越界访问而停止。
3. 递归分界点的选择,为什么以 j 划分,不能让 x=arr[r];以 i 划分,不能让 x=arr[l]呢。
     以 j 划分为例,首先我们可以知道myQuickSrot(arr, j+1 , r)这个递归是不会进入死循环的,因为 j+1 始终会改变再次进入函数的 l 值。myQuickSrot(arr, l, j)这个递归却有出现 死循环的可能,原因就是,程序永远会走到 arr[l..r-1]<=x , arr[r]=x;当这一步继续执行就是 i=r,j=r; 而这就是进入本次循环的 j 是相同的,所以就会这样无限划分下去。
4. while(i < j) 能否改为 while(i <= j)
   答案是不能的,因为在某些情况下,j=l-1 的此时会造成数组越界访问。
      比如说 在数组只剩 [a,b] 且 a<b 时,这种情况下,初始 i = l - 1, j = r + 1,第一轮 while 循环结束 i = l, j = l,第二轮 while 循环结束 i = r, j = l-1。而 j = l-1 会造成数组越界访问,while(i<j) 就不会,因为在第一次while循环结束后,就跳出此次循环了。
    有些人可能会疑惑: 这种情况看起来比较极端啊, 如果构造数组 [3, 2, 1] 会不会就不会遇到这种情况了,其实不然, 因为快排是分治算法, 往下递归时总会遇到 [a, b], a < b 这种情况,只要有一个这种情况, 就会进入无限划分出不来.

public static void main(String args[]) {
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int[] arr = new int[n];

        for (int i = 0; i < n; i ++) {
            arr[i] = sc.nextInt();
        }

        myQuickSrot(arr,0,n - 1);

        for(int i = 0; i < n; i++) {
            System.out.print(arr[i]+" ");
        }
    }
    public static void myQuickSrot(int[] arr,int l,int r) {
        if(l >= r) {
            return ;
        }

        int i = l - 1;
        int j = r + 1;
        int x = arr[r+l >> 1];

        while(i < j) {
            do i++; while(arr[i] < x);
            do j--; while(arr[j] > x);
            if (i < j) {
                int t = arr[i];
                arr[i] = arr[j];
                arr[j] = t;
            }
        }

        myQuickSrot(arr,l,j);
        myQuickSrot(arr,j + 1,r);
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值