快速排序QuickSort

第一版

要求

使用递归,partion函数将小于目标值的放在左边,大于目标值的放在右边,并返回目标值的位置,以便递归

思路

使用j和i指针,j指向目标值(左边),i指向l+1,两个循环不变量如图,如果i的值比目标值小的化,交换i的值和j+1的值,j++
在这里插入图片描述

循环不变量

[l+1,j] < v
[j+1,i-1] >v

代码

import java.util.Arrays;

public class QuickSort {
    public static <E extends Comparable<E>> void Sort(E[] arr){
       Sort(arr,0,arr.length-1);
    }
    private static <E extends Comparable<E>> void Sort(E[] arr , int l , int r){
        if(l >= r)
            return;
        int a = partition(arr,l,r);
        Sort(arr,l,a-1);
        Sort(arr,a+1,r);
    }
    public static <E extends Comparable<E>> int partition(E[] arr,int l ,int r){
        int j = l;
        for (int i = l+1; i <= r; i++) {
            if(arr[i].compareTo(arr[l])<0){
                j++;
                swap(arr,i,j);
            }
        }
        swap(arr,l,j);
        return j;
    }
    public static <E>void swap(E[] arr,int i , int j){
        E temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        Integer[] arr = {3,1,4,5,2,6,0};
        Sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

问题1

在这里插入图片描述

当数组是有序的时候时间复杂度较大

改进

在partition中加入随机索引

int randomIndex= random.nextInt(r - l + 1) + l;
//nextInt取的是开区间所以要加一
swap(arr,l,randomIndex);

时间复杂度分析

虽然加了随机标定,但当数组元素都相等时,100%恶化,故仍为O(n2)

问题2

在这里插入图片描述

如果所有元素相等,和问题1一样,最后会得到左边没有元素的情况

改进

//把此处的判断条件加上等于
if(arr[i].compareTo(arr[l])<=0)

第二版(实现双路排序)

要求

使用i和j指针,i指向l+1的元素,j指向r的元素,运用两个循环使得两个指针向中间移动

思路

小循环的条件即为两指针之间有元素(i<=j),如果比标定值小或者大就向中间移动,当i>=j时循环结束,小循环结束后交换两元素,继续向中间移动

代码

    public static <E extends Comparable<E>> int partition2ways(E[] arr,int l ,int r){
        int i = l + 1;
        int j = r;
        int randomIndex= random.nextInt(r - l + 1) + l;
        swap(arr,l,randomIndex);
        while (true){
            while (i <= j && arr[i].compareTo(arr[l])<0) i++;
            while (i <= j && arr[j].compareTo(arr[l])>0) j--;
            if(i >= j) break;
            swap(arr,i,j);
            i++;
            j--;
        }
        swap(arr,l,i);
        return i;
    }

时间复杂度分析

和归并排序一样为O(nlogn)
在这里插入图片描述
在这里插入图片描述

第三版(实现三路排序)

要求

在这里插入图片描述> 在这里插入图片描述

思路

三个指针,三个循环不变量,初始值lt=l, i=l+1 ,gt=r+1 如图,循环条件为i<gt,结束后应该
[l,lt-1]<v
[lt,gt-1]=v
[gt,r]>v

循环不变量

[l+1,lt] < v
[lt+1,i-1] = v
[gt,r] > v

代码

private static <E extends Comparable<E>> void Sort3ways(E[] arr , int l , int r){
        if(l >= r)
            return;
        int randomIndex= random.nextInt(r - l + 1) + l;
        swap(arr,l,randomIndex);
        int lt = l,i = l+1,gt = r+1;
        while (i<gt){
            if(arr[i].compareTo(arr[l])<0){
                lt++;
                swap(arr,lt,i);
                i++;
            }else if(arr[i].compareTo(arr[l])>0){
                gt --;
                swap(arr,gt,i);
            }else {
                i++;
            }
        }
        swap(arr,l,lt);
        Sort3ways(arr,l,lt-1);
        Sort3ways(arr,gt,r);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java_zxh_03

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值