排序之快速排序

分治法

  1. 分解问题
  2. 解决子问题
  3. 合并子问题的解

这里写图片描述


快速排序思想

分治法:递归
1. 选取privot(中枢):随机的选取一个元素作为中枢;
2. 分割策略:partition算法将数组进行分割,使中枢左边的数组元素均小于中枢,中枢右边的数组元素均大于中枢;
3. 这样就分解为两个子数组,分别对子数组进行递归操作。


代码实现

package sort;

import java.util.Random;

public class QuickSort {
    /**
     * 快速排序的递归实现
     * @param data 待排序数组
     * @param start
     * @param end
     */
    public static void quickSort(int[] data, int start, int end) {
        if (data == null || data.length <= 0 || start < 0 || end < 0 || data.length <= start || data.length <= end) {
            throw new IllegalArgumentException("Invalid parameters in partition method!");
        }
        if (start == end) {
            return;
        }
        int index = partition(data, start, end);
        if (index > start) {
            quickSort(data, start, index - 1);
        }
        if (index < end) {
            quickSort(data, index + 1, end);
        }
    }

    /**
     * 随机选取算法
     * @param data
     * @param start
     * @param end
     * @return
     */
    public static int partition(int[] data, int start, int end) {
        if (data == null || data.length <= 0 || start < 0 || end < 0 || data.length <= start || data.length <= end) {
            throw new IllegalArgumentException("Invalid parameters in partition method!");
        }
        int index = new Random().nextInt(end - start + 1) + start;
        swap(data, index, end);

        int small = start - 1; //指向最后一个小于data[end]的元素
        for (index = start; index < end; index++) {
            if (data[index] < data[end]) {
                small++; //data[index]待放入的位置
                if (small != index) {
                    swap(data, small, index);
                }
            }
        }
        small++; //放置data[end]
        swap(data, small, end);

        return small;
    }

    /**
     * 交换数组中两个元素
     * @param data
     * @param p
     * @param q
     */
    public static void swap(int[] data, int p, int q) {
        if (data == null || data.length <= 0 || p < 0 || q < 0 || data.length <= p || data.length <= q) {
            throw new IllegalArgumentException("Invalid parameters in swap method!");
        }
        int tmp = data[p];
        data[p] = data[q];
        data[q] = tmp;
    }

}

性能分析:不稳定

最坏情况的划分:每一次递归,划分都是最大程度不平衡的,即T(n)=T(n-1)+T(0)+n=O(n*n)
例如:若输入的数组是已排序(升序)的,并且此时快速排序选取最后一个元素作为中枢(不是随机选取的),那么快速排序的时间复杂度就是O(n*n)。而此时插入排序的时间复杂度最小,为O(n)。

最好情况的划分:最平衡的划分,即T(n)=2T(n/2)+n=O(nlogn)
这里写图片描述

平均情况的划分:只要划分是常数比例的,运行时间总是O(nlogn)
例如:即T(n)=T(9n/10)+T(n/10)+cn=O(nlogn),可以通过递归树证明。


应用

partition算法的特点是通过一次遍历,以中枢元素将数组分割成两部分,前部<中枢<=后部。
partition算法和递归结合可以用于解决面试题29 :数组中出现次数超过一半的数字面试题30:最小的k个数、第k大的数字等问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值