资讯专栏INFORMATION COLUMN

【算】快速排序

godiscoder / 2772人阅读

摘要:分治快速排序以下简称快排的核心思想是分治法。第二个元素大于,放于右侧第三个元素小于,放于左侧以此类推,最后一个元素放置完毕后是这样的重复。此时从左到右读出图中曾作为基准值的元素菱形,我们发现已经排序好了。

分治

快速排序(以下简称“快排”)的核心思想是分治法。可以说,分治提供了另一种解决问题的思路。举个例子来进行说明,抓稳扶好,直接开车了……

举例

现有一个集合{4,8,2,5,7,-1,3},我们将对它进行从小到大排序:

1.选取第一个元素4作为基准值,后面的元素逐个和这个基准值比较大小

显然,要么大于,要么小于( 暂不考虑相等的情况)。

2.按比较大小结果进行安置:大于基准值的元素,置于它的左侧;小于基准值的元素,置于它的右侧(如果有相等情况,左右随意)

为好理解,画出了数轴,将"基准值4"作为中轴线。第二个元素8大于4,放于右侧;第三个元素2小于4,放于左侧……以此类推,最后一个元素放置完毕后是这样的

3.“重复”。先抛开右侧的big集合,专注于左侧集合{2,-1,3}。此时,我们把它当作source,重复第一步的操作。

如此重复下去,直到只剩下一个元素的情况。

此时从左到右读出图中曾作为基准值的元素(菱形)——-1,2,3,4,我们发现已经排序好了。最后给出完整的操作示意图:

每次根据条件划分成两部分,划分后每部分分别治理,即分治。

递归

上面的例子中,第三步叫“重复”其实并不准确,真正的名字是递归

每个递归函数都有两部分

基线条件:函数不再调用自己,即退出无限循环调用的条件

递归条件:调用自己,且通过一次次调用会逐步靠拢基线条件

拿上一篇文章(【算】选择排序和二分查找)里聊过的二分查找举例:

/**
 * 二分查找,递归版
 * @param target
 * @param source
 * @return
 */
public static int doFind(int target,List source){
    if(CollectionUtils.isEmpty(source)){
        throw new RuntimeException("集合为空");
    }
    int halfIndex = source.size()/2;
    int halfElement = source.get(halfIndex).getVal();
    if(target==halfElement){    //基线条件:如果目标target和中间数相等,bingo!找到了,返回索引
        return source.get(halfIndex).getIndex();
    }else if(source.size()==1){ //另一个基线条件:就剩下最后一个元素了,仍然与目标target不符,则返回“目标不存在”
        throw new RuntimeException("目标不存在");
    }else{  //递归条件:选取符合条件的那一半集合,递归调用自己
        if (target < halfElement) {
            List tempSource = source.subList(0, halfIndex);
            return doFind(target, tempSource);
        } else {
            List tempSource = source.subList(halfIndex, source.size());
            return doFind(target, tempSource);
        }
    }
}
快排

掌握了递归和分治思想后,快速排序就只剩下编码部分了:

/**
 * 快排
 * @param source
 * @return
 */
public static List doOrder(List source){
    if(source.size()<=1){   //基线条件
        return source;
    }
    int temp = source.get(0);
    List lowElements = new LinkedList<>();
    List highElements = new LinkedList<>();
    for(int i=1,len=source.size();i res = new LinkedList<>(lowElements);
    res.add(temp);
    res.addAll(highElements);
    return res;
}

快排的平均时间复杂度O(n log n)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68860.html

相关文章

  • Java排序法之——快速排序

    摘要:代码片段语言组织能力有限,直接上代码排序算法之快速排序参数为需要排序的数组参数为数组的起始下角标即参数为数组的最后下角标即经过一轮排序,已经将数组分为左右两部分进行递归排序总结快速排序的精髓在于分治思想,分而治之,它的时间复杂度为。 算法简述 所谓快速排序算法是基于交换排序和递归思想的,它的速度的确如名字所示——快!并且这种一算一般被用作数量级比较大的数据当中,在大数据中有着很重要的地...

    Yangyang 评论0 收藏0
  • PHP 快速排序

    摘要:概念这里借用百度百科的一张图来,非常形象快速排序算法是对冒泡算法的一个优化。获取已经打乱了顺序的数组快速排序这里引用的是我之前写的冒泡算法排序冒泡运行结果 概念 这里借用百度百科的一张图来,非常形象:showImg(https://segmentfault.com/img/bVdlR6); 快速排序算法是对冒泡算法的一个优化。他的思想是先对数组进行分割, 把大的元素数值放到一个临时数...

    Coly 评论0 收藏0
  • javascript中数组的回顾

    摘要:数组在中使用度非常频繁,我总结了一些在数组中很常见的问题。否则返回语言类型返回数组中满足提供的测试函数的第一个元素的索引。接受两个参数和,代表需要截取的数组的开始序号和结束序号。其中表示添加的元素个数。 数组在javascript中使用度非常频繁,我总结了一些在数组中很常见的问题。 关于数组中的方法非常多,我总结了一张表来大致了解数组中的方法 Array中的方法 含义 改变原数组 ...

    gaomysion 评论0 收藏0
  • 【数据结构初阶】第九篇——八大经典排序法总结(图解+动图演示+代码实现+八大排序比较)

    摘要:本篇博客我要来和大家一起聊一聊数据结构初阶中的最后一篇博客八大经典排序算法的总结,其中会介绍他们的原来,还有复杂度的分析以及各种优化。快速排序递归版本快速排序是于年提出的一种二叉树结构的交换排序方法。 ...

    xiaowugui666 评论0 收藏0

发表评论

0条评论

godiscoder

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<