排序算法讲解(2)——快排

快速排序

思想

快排采用了分治的思想,每次分治,将数组一分为二,选取数组中一个元素作为标准,将小于标准的数分为一个数组,将大于标准的数分为一个数组

,然后在对这两个新数组进行分治,直到每个子数组都有序,数组也就被排序好了。

算法过程

以递增排序为例

  • 定义一个头指针指向头部,定义一个尾巴指针指向尾部
  • 定义一个划分标准flag,这里直接以头指针指向的数字作为flag(注意头指针指向flag)
  • 尾指针向左移动,直到找到一个数字小于flag
  • 尾指针和头指针的数字交换(这时候尾巴指针指向flag)
  • 头指针向右边移动,直到找到一个数字大于或等于flag
  • 交换(这时候头指针指向flag)
  • 重复以上步骤直到两指针相遇
  • 将头指针或者尾巴指针作为小值数组的右边界和大值数组的左边界,开始分治
  • 直到数组的分界线重合,结束分治

示例代码

import java.util.Arrays;
import java.util.Random;

public class QuickSort {

    public static void sort(int[] nums) {
        int len = nums.length;
        if (len <= 1) {
            return;
        }
        helper(0, len - 1, nums);
    }

    private static void helper(int left, int right, int[] nums) {
        if (left >= right) { return; }
        int i = left;    //头指针
        int j = right;   //尾指针
        int flag = nums[left];  //标准
        //直接交换flag
        while (i < j) {
            while (nums[j] >= flag && i < j) { j--; } //左移到小于标准的值
            if (i < j) {   // 交换
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
            while (nums[i] < flag && i < j) { i++; } // 右移动到大于等于标准的值
            if (i < j) {  //交换
                int temp = nums[i];
                nums[i] = nums[j];
                nums[j] = temp;
            }
        }
        helper(left, i - 1, nums);      //分治
        helper(i + 1, right, nums);   
    }

    public static void main(String[] args) {
        int[] test = new Random().ints(1,20).limit(20).toArray();   //生成一个随机测试集合
        Arrays.stream(test).forEach(x-> System.out.print(x+" "));
        System.out.println();
        sort(test);
        Arrays.stream(test).forEach(x-> System.out.print(x+" "));
    }
}
	

算法分析

稳定性

快排是不稳定的,可能会出现相同值对换的情况,比如:2 2 2 1 1 1 2 2 2 ,第二个2会被交换到第三个2的后面

复杂度

在最好的情况下,即每次标准的几乎能吧数组刚好分成数量相同的两半的时候,时间复杂度是O(nlog(n))

在最坏的情况下,比如一个排序好的数组,每次将数组分成1数字和剩余的数字,这样就要递归n次,时间复杂度为O(n^2)

优化角度

划分标准优化:标准的选择对算法有不小的影响,上面的示例中默认以头指针作为标准,这样有可能会遇到最坏的情况,可以采用随机数或者三数取中法(头值,尾值,n/2的值三个数的中值)来选取标准来避免最坏的情况

其余优化:递归优化,分治小到一定的规模是采用插排,每次划分后将与标准值相等的数聚集在一起等等。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值