快排算法详解快速排序详解多图详解

1.快排的基本原理:

第一步,完成相对一个数的有序

声明一个变量i

总共就有三种情况:

(1)arr[i]<num,arr[i]与<区域的右边的第一个数做交换,小于等于区域向右移动,i++

(2)arr[i]==num,小于num区域不移动,i++

(3)arr[i]>num,arr[i]与>区域左边第一个数做交换,大于等于向左移动,注意:i大小此时没有发生变化

循环以上过程,则可以达到这样的结果

数组经过这样的排序以后就完成相对一个数的有序【这里的排序只是指把小于num的数放左边,等于num的数放中间,大于num的数放右边,而在小于num的数的范围里并没有固定的次序,大于也一样】

而此时再将数组小于num的部分和大于num的部分分别递归就可以完成全部排序。

举例:

当num = 5的时候:

注意:只有a[i]<=num的时候,i++

 最终就可以完成小于num的数在左边,等于num的数在中间,大于num的数在右边

 

2.现在的快排算法

再使用上面的递归算法之后,以前的快排算法是将整个数组的最后一位作为整个数组的num,再执行上面的递归算法。因为数组顺序的不确定性,当数组处于最坏的情况时,即从大到小的情况时【目前介绍的是从小到大排序,总之就是你需要排的顺序不一样】比如:5,4,3,2,1,此时选最后一个数的时间复杂度为O(N^2)。为了避免这种情况,最新的排序算法选择num采用了随机的方式,即在数组长度范围内随机生成一个i,交换a[i]和数组最后一位,然后再将最后一位作为num【即将a[i]的值当作num】

下面是举例代码:

import java.util.Scanner;
public class HeNanGuoQiWenTi{
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int[] a = new int[5];
        for(int i=0;i<a.length;i++) {
            a[i] = scanner.nextInt();
        }
//输入5个数作为举例数组
        quickSort(a,0,a.length-1);//L和R分别为数组的左边界和右边界
        for(int i=0;i<a.length;i++){
            System.out.println(a[i]);
        }
    }
    public static void quickSort(int[] a,int L,int R) {
        if(L<R) {
            swap(a,L+(int)(Math.random()*(R-L+1)) , R);//随机生成一个数i,假定这个随机数值为a[i],使得a[i]与数组的最后一位数做交换
            int[] p = progress(a, L, R);
            //返回的这个p数组即为相同的a[i]在经过排列后,相同a[i]所占的下标a[p[0]]=a[p[1]=...=a[p[p.length-1]]
            quickSort(a,L,p[0]-1);//小于a[i]部分继续递归
            quickSort(a, p[1]+1, R);//大于a[i]部分继续递归
        }

    }
    private static int[] swap(int[] arr,int i,int j) {//交换值
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
        return arr;
    }
    public static int[] progress(int[] a,int L,int R) {
        int less = L-1;
        int more = R;
        //因为swap(a,L+(int)(Math.random()*(R-L+1)) , R);意思就是交换a[i]和a[R],就是说数组中最后一位就为上面的num,所以说大于区域是从R开始,而不是R+1开始
        while (L<more) {//当L==more时候,刚好将需要的部分遍历完
            if(a[L]<a[R]) {
                swap(a, ++less, L++);
            } else if(a[L]>a[R]) {
                swap(a, --more, L);
            }else {
                L++;
            }
        }
        swap(a, more, R);
        return new int[] {less+1,more};
        /*当相同的数只有一个时,less+1和more【less+1和more均为数组a的下标】是相等的,当相同的数有两个时,a[less+1]==a[more],
        返回的两个下标刚好也是这两个相同的数的下标,最重要的是,无论你是什么数组,经过progress方法以后,返回的这两个数刚好就是排好序后中间那段相同的数的下标
         */
    }
}

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值