快速排序(递归)

思路:每次排序选择中间的一个数作为基准,将左边大于基准值的和右边小于基准值的调换,如果左边有而右边没有或者右边有左边没有的话就是将基准值与该数调换位置,注意这个基准值只是一开始取的是中间的数,不能保证一轮排序之后还位于中间位置。一轮排序之后就进行左右递归。

第一步:选好一个基准值(以中间值为例,也可以选其他地方的),分别从排序左右两边开始将数据与基准值进行比较,分别找到左边比基准值大的数的下标以及右边比基准值小的数的下标,然后进行交换,直到左下标大于等于右下标。

while (l < r) {
            //把左边大于pivot的找出来
            while (arr[l] < pivot) {
                l += 1;
            }
            //把右边小于pivot的找出来
            while (arr[r] > pivot) {
                r -= 1;
            }
            //查找一遍过后,如果发现l=r,说明两边已经有序了
            if (l >= r) {
                break;
            }
            //开始调换位置
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            /*如果交换位置之后发现交换的值跟基准值相等,说明该位置的值可能即使基准值或者是与基准值相等的数字(这种情况不用考				虑,不会影响排序)我们要跳开调换过后的这个数字去拿它的下一个进行比较,否则会一直停留在位置来回将这个数字与基准值进行				比较,进入死循环,出不来
             * */
            if (arr[l] == pivot) {
                r -= 1;
            }
            if (arr[r] == pivot) {
                l += 1;
            }
        }

第二步:第一次排序之后,在基准值左边都是比它小的,右边都是比它大的了,我们就要进一步缩小排序,从它的左边和右边开始递归比较,继续将左边和右边分别分成两个部分再进行相同的排序,以此类推,到最后每部分都之后一个元素的的时候,我们就可以得到一个有序的序列了。

 /*
        * 说明基准左边的都小于基准值,右边的都大于基准值,这时我们可以进行下一步递归了,而下一步递归可以跳过本次这个基准值
        * */
        if (l == r) {
                l += 1;
                r -= 1;
            }
       //System.out.println(Arrays.toString(arr));
        if (left < r){
            quickSort(arr,left,r);
        }
        if (right > l){
            quickSort(arr, l, right);
        }

完整代码

public class QuickTest {
    public static void main(String[] args) {
        int[] arr = {8, 12, 19, -1, 45, 0, 14, 4, 11};
        //int[] arr = {1, 7, 3, 4, 6, 8, 7, 6, 11,32,42,26,56,1,89,2,98,67};
        //测试快排的执行速度
        // 创建要给 80000 个的随机的数组
        /*int[] arr = new int[800000];
        for (int i = 0; i < 800000; i++) {
            arr[i] = (int) (Math.random() * 800000);
            // 生成一个[0, 8000000) 数
        }*/
        //System.out.println(Arrays.toString(arr));
        System.out.println("排序前");
        Date data1 = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat.format(data1);
        System.out.println("排序前的时间是=" + date1Str);
        QuickSort quickTest = new QuickSort();
        quickTest.quickSort(arr, 0,arr.length - 1);
        System.out.println("排序后");
        Date data2 = new Date();
        String date1Str2 = simpleDateFormat.format(data2);
        System.out.println("排序后的时间是=" + date1Str2);
    }
}

class QuickSort {

    /**
     * 快速排序
     * @param arr 待排序的数组
     */
    public void quickSort(int[] arr,int left,int right) {
            int l = left;
            int r = right;
            int pivot = arr[(left + right) / 2];
            int temp = 0;
            //第一步,先将把小于pivot的放到pivot的左边,大于的放到右边
        while (l < r) {
            //把左边大于pivot的找出来
            while (arr[l] < pivot) {
                l += 1;
            }
            //把右边小于pivot的找出来
            while (arr[r] > pivot) {
                r -= 1;
            }
            //查找一遍过后,如果发现l=r,说明两边已经有序了
            if (l >= r) {
                break;
            }
            //开始调换位置
            temp = arr[l];
            arr[l] = arr[r];
            arr[r] = temp;
            /*如果交换位置之后发现交换的值跟基准值相等,说明该位置的值可能即使基准值或者是与基准值相等
            的数字(这种情况不用考虑,不会影响排序)我们要跳开调换过后的这个数字去拿它的下一个进行比较,
            否则会一直停留在位置来回将这个数字与基准值进行比较,进入死循环,出不来
             * */
            if (arr[l] == pivot) {
                r -= 1;
            }
            if (arr[r] == pivot) {
                l += 1;
            }
        }
        /*
        * 说明基准左边的都小于基准值,右边的都大于基准值,
        * */
        if (l == r) {
                l -= 1;
                r += 1;
            }
       System.out.println(Arrays.toString(arr));
        if (left < l){
            quickSort(arr,left,l);
        }
        if (right > r){
            quickSort(arr, r, right);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值