快速排序

快速排序

快速排序由托尼 · 霍尔于1961年提出。

  1. 分解原问题

    数组 arr[p…r] 被划分为两个(可能为空)子数组 arr[p…q - 1] 和 arr[q + 1,…r],使得 arr[p…q - 1] 中的每一个元素都小于等于 arr[q],arr[q + 1,r] 中的每一个元素都大于等于 arr[q]。

  2. 解决子问题

    递归调用快速排序,对子数组 arr[p…q - 1] 和 arr[q + 1…r] 进行排序。

  3. 合并问题解

    对于快速排序来说,数组进行的是原址排序,所以不需要进行合并操作。

数组划分(Partition)

数组划分 Partition O(n) 主元一般选择尾位,也可任意选,之后再与尾位交换,且这个过程的时间复杂度为O(1),与直接选择尾位作为主元无异。

在这里插入图片描述

Partition 的每一次迭代中都会有两种不同的情况:

<1>. 如果 arr[ i ] > X,需要做的只是将 j 的值加 1。

<2>. 如果 arr[ i ] <= X,则要将 i 的值加1,并交换 arr[ i ] 和 arr[ j ],再将 j 的值加1。

伪代码

在这里插入图片描述

在这里插入图片描述
最好情况 : nlogn

最坏情况 : n2

代码实现

public static int Partition(int[] arr,int p, int r){
    int temp;
    int X = arr[r];
    int i = p - 1;
    for(int j = p; j <= r - 1; j++){
        if(arr[j] <= X){
            i = i + 1;
            temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    temp = arr[i + 1];
    arr[i + 1] = arr[r];
    arr[r] = temp;
    int q = i + 1;
    return q;
}
public static int[] QuickSort(int[] arr,int p,int r){
    int q;
    if(p < r){
        q = Partition(arr,p,r);
        QuickSort(arr,p,q - 1);
        QuickSort(arr,q + 1,r);
    }
    return arr;
}

算法实例

在这里插入图片描述

在这里插入图片描述

随机化的快速排序

随机划分,主元先随机选,之后与最后一个元素交换

期望复杂度为:O(nlogn)

在这里插入图片描述
代码实现

public static int RandomizedPartition(int[] arr,int p,int r){
    // 在arr中随机选取主元
    Random random = new Random();
    int s = random.nextInt(r)%(r-p+1) + p;
    // 将选取的主元与arr最后一个元素交换
    int temp = arr[s];
    arr[s] = arr[r];
    arr[r] = temp;
    return Partition(arr,p,r);
}
public static int[] RandomizedQuickSort(int[] arr,int p,int r){
    int q;
    if(p < r){
        q = RandomizedPartition(arr,p,r);
        RandomizedQuickSort(arr,p,q - 1);
        RandomizedQuickSort(arr,q + 1,r);
    }
    return arr;
}

在这里插入图片描述

归并排序侧重合并过程,简化分解过程
快速排序侧重分解过程,简化合并过程

基于两个元素比较的排序算法的算法下界为O(nlogn)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值