zoukankan      html  css  js  c++  java
  • 几种不常用的排序算法

    基于比较大排序算法至少需要O(n*lgn)的复杂度。对于一些特殊的输入我们有一些特殊的算法,有可能得到复杂度为O(n)的算法。本文简要描述其中的几种:count排序,基数排序和桶排序。

    count排序的假设是被排序的字段在一个有限的范围内,比如对1000人按照年龄排序。

    count排序需要两个额外的变量,一个用于存放排序结果,长度是n,另一个用于存放中间结果,长度是k。其中n为输入的长度,k-1为输入数据的最大值。

    设输入A[0..n-1],初始化变量 B[0..n-1], C[0..k-1],算法如下:

    for i = 0 .. k-1
        C[i] = 0
    for j = 0 .. n-1
        C[A[j]] ++
    for i = 1 .. k-1
        C[i] = C[i-1] + C[i]
    for j = n-1 .. 0
        B[C[A[j]]-1] = A[j]
        C[A[j]] --

    容易证明这个算法复杂度为O(n+k)。考虑到k一般为O(n),所以整体复杂度为O(n)。

    基数排序的起源是扑克牌的排序,先按照花色排序,再按照数字排序。如果要对一些10进制数排序,比如:123,456,321,789.可以按照从低位到高位的顺序,先第一位排序,再第二位排序,依次类推。需要注意两点:

    1. 必须先低位后高位,因为高位更有决定权,只有当高位一样的时候,才按照低位到顺序排序,这就是第二点:

    2. 按照某位排序时,排序算法必须是稳定的;

    算法很简单:

    for i = 1..b

       按照第i位排序,稳定排序

    很容易看到这个复杂度是O(b*(n+k)),其中n是输入元素个数,k是输入元素在某个位上元素个数。b是输入元素的位数。

    稍微变化一下,不是每位排序一次,而是分成若干组,每组有r位,那么复杂度为O(b/r * (n+2^r))。以r为变量,对这个表达式求最小值。分几种情况:

    1. b<lgn,由于r小于b,故2^r小于n,因此复杂度为O(n)

    2. b>=lgn,取r=lgn,复杂度也是O(n)

    桶排序

    桶排序更类似于count排序的连续版本。count排序需要输入是整数。桶排序假设输入在0~1区间均匀分布。假设输入A[1..n],满足A[i]小于1,大于等于0,后我们把该0~1等分成n份,每份是一个bucket。然后用B数组[1..n]分别存放对应区间的A的元素,并对这些元素使用插入排序。最后将B的各个元素对应的list串联起来。比较麻烦的是这个算法的复杂度证明。结论是如果输入的分布满足均匀分布,那么复杂度为O(n).

  • 相关阅读:
    addEventListener 事件监听器 冒泡事件)
    内置对象 Date
    js-定时器
    BOM:浏览器对象
    DOM元素
    js控制style样式
    【应急响应】Windows 安全加固
    【渗透测试】社会工程学,没有射不下来的人
    【代码学习】PYTHON 线程
    【代码学习】PYTHON 进程
  • 原文地址:https://www.cnblogs.com/alphablox/p/2912616.html
Copyright © 2011-2022 走看看