快速排序

快速排序


一、思路:

  1.  从待排的数组中选出来一个基准数(key)
  2.  遍历整个数组,将比key小的放在左边,比key大的放在右边
  3.   分别对左右两个小区间用相同的方式进行处理
  4.   直到小区间的size=1或0(小区间有序或没有数据)

二、拿一个数组进行快速排序:



三、代码实现:


大思路:

​
public static void quicksort(long[] array) {
        //一个内部的快速排序
        quicksortInternal(array,0,array.length-1);
    }

    public static void quicksortInternal(long[] array,int lowIndex,int highIndex) {
        int size = highIndex - lowIndex + 1;
        if(size <= 1) {
            return;
        }
        //1.找到一个基准数(最左边的数)
        long key = array[lowIndex];
        //2.执行partition的过程,将小的放的前面大的放到后面
        int keyIndex = partition(array, lowIndex, highIndex);//返回partition之后下一次key位置的下标
        //分别对左右区间进行相同的处理
        quicksortInternal(array, lowIndex, keyIndex - 1);
        quicksortInternal(array, keyIndex + 1, highIndex);
    }

​


遍历数组,将数组分为两个小区间(小的放左,大的放右)


Hoare法:


要遍历的区间[lowIndex ,rightIndex]

 

  • 选最左边的数为key 
  • 从右边开始走:
  1.    rightIndex --;直到遇到小于 key 的数停下来
  2.    leftIndex++; 直到遇到大于 key 的数停下来
  3.  交换leftIndex 和rightIndex 位置的数 
  • 交换lowIndex 和leftIndex位置的数(此时letIndex和rightIndex 指向的是同一位置)
  •  返回leftIndex
 private static int partitionHoare(long[] array, int lowIndex, int highIndex) {
        int leftIndex = lowIndex;
        int rightIndex =highIndex;
        //选择最左边的数
        long key = array[lowIndex];
        //选择了左边的数,从右边开始走
        while (leftIndex < rightIndex){
        //由于leftIndex 和 rightIndex 在不同的变化,所以要在里面的循环保证leftIndex 小于rightIndex
            while (leftIndex < rightIndex && array[rightIndex]>=key){
                rightIndex--;
            }
            //说明遇到了小于key的数
            while (leftIndex < rightIndex && array[leftIndex] <= key) {
                leftIndex++;
            }
            //说明遇到了大于key的数
            swap(array,rightIndex,leftIndex);//交换两个数
        }
        swap(array,lowIndex,leftIndex);
        return leftIndex;
    }
    private static void swap(long[] array, int rightIndex, int leftIndex) {
        long t = array[rightIndex];
        array[rightIndex] = array[leftIndex];
        array[leftIndex] = t;
    }


挖坑法:

实质上和Hoare方法是一致的,只是将交换的过程变成了挖坑、填坑的过程。

private static int partition(long[] array,int lowIndex,int highIndex){
        int leftIndex = lowIndex;
        int rightIndex =highIndex;
        
        long key = array[lowIndex];//挖坑
        while (leftIndex < rightIndex) {
            while (leftIndex < rightIndex && array[rightIndex] >= key) {
                rightIndex--;
            }
            array[leftIndex] = array[rightIndex];
            while (leftIndex < rightIndex && array[leftIndex] <= key){
                leftIndex++;
            }
            array[leftIndex] = array[rightIndex];
        }
        //填坑
        array[leftIndex] = key;
        return leftIndex;
    }


前后遍历法

private static int parition前后(long[] array,int lowIndex,int highIndex){
        int separateIndex = lowIndex +1; //用来分隔,当出现小于lowIndex位置的数时,交换,separateIndex往后走
        for(int i = lowIndex+1;i<=highIndex;i++) {//用来遍历数组
            if(array[i] < array[lowIndex]) {
                swap(array,i,separateIndex);
                separateIndex++;
            }
        }
        swap(array,lowIndex,separateIndex-1);
        return separateIndex-1;
    }


四、性能分析:

时间复杂度空间复杂度
最好平均最坏最好平均最坏
O(n*log(n))O(n*log(n))O(n^2)O(log(n))O(log(n))O(n)

时间复杂度:每做一层数组的partition的时间复杂度为O(n),一共有多少层看执行partition的次数,最好为O(log(n)),最坏为O(n)(二叉树的高度)

稳定性:不具备稳定性,在进行partition的过程中不能保证相等的数保持原来的顺序。

五、优化:

1.在选择基准数上进行优化(左边或右边,随机选取,几个数取中间值)

2.当区间内的个数低于某个阈值时(16)时,使用插入排序更快

3.把相等的值进行特殊处理

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值