归并排序比较次数_计数排序

6b07e05b178fea2d20429304594fbb07.png

时空权衡

在前面的章节里,我们知道归并排序是一种高效的排序算法,在任何情况下时间复杂度都为

。但是,
它需要用额外的内存空间来暂时储存归并过程中的元素,因此我们可以认为归并排序是以牺牲一部分内存空间为代价来获得时间的高效性。相反,如果内存空间有限,我们就 必须以牺牲时间为代价来保证空间不被过度使用。像上面所说的那样,在设计一个算法的过程中同时考虑时间复杂度和空间复杂度,并且在这两者中找到一个平衡点的过程我们把它称作 时空权衡time and space trade-off)。

fcdc316654d9fa870000610479fffa7d.png

在通常情况下,我们都认为时间更宝贵,而空间相对廉价。因此在大多数情况下,我们都是以牺牲空间的方式来减少运行时间。

计数排序

计数排序counting sort)就是一种牺牲内存空间来换取低时间复杂度的排序算法,同时它也是一种不基于比较的算法。这里的不基于比较指的是数组元素之间不存在比较大小的排序算法,我们知道,用分治法来解决排序问题最快也只能使算法的时间复杂度接近

,即
基于比较的时间复杂度存在下界
,而不基于比较的排序算法可以突破这一下界。

下面我们就来介绍一种不基于比较的排序算法:计数排序。我们用一种通俗方式来理解这个过程过程。如下图所示,假设我们用不同大小的小球来表示每一个数组元素的值,我们的目标是使小球从小到大以次排列。

045c1e5ee8e93371fa10af2924936084.png

首先我们需要知道最大的球和最小的球分别对应的元素,这里最大的对应

,最小的对应

f87cab0757ba8730249206886f2a85b9.png

然后我们需要用

个计数器来分别统计
之间每种小球的个数
(假设
之间的小球对应的元素均为整数),下图中我们用带有标记的桶来表示。

c83a05e2576d22c1fa93b25a068ad658.png

接下来,我们遍历所有的小球,将每个值为

的小球放入到第
个桶中,比方说第一个小球的值为
,那么我们就把它放到标号为
,也就是从左往右第
个桶中,放入后计数器加

1dbaf629808966adf5adeb951d35e431.png

最后,我们从左往右依次将每个桶里的小球取出,每取出一个小球,对应桶的计数器减

,直到计数器为
,将所有桶内的小球都取出后,小球就是从小到大排列了。

9e0506f68baa0edd6d547fa31b21eeea.png

我们用一个动画来完整地看一看这个过程。

821ab6187eb4d36c8f4250692f2a6246.png
视频来源:https://visualgo.nethttps://www.zhihu.com/video/1239332342818758656

代码实现:

def counting_sort(array):
    largest = max(array); smallest = min(array)  # 获取最大,最小值
    counter = [0 for i in range(largest-smallest+1)]  # 用于统计个数的空数组
    idx = 0  # 桶内索引值
    for i in range(len(array)):
        counter[array[i]-smallest] += 1  # 统计每个元素出现的次数
    for j in range(len(counter)):
        while counter[j] > 0:
            array[idx] = j + smallest  # 取出元素
            idx += 1
            counter[j] -= 1
    return array

整个过程需要遍历两次数组,一次是遍历长度为

的数组,另一次是从计数器(假设有
个计数器)中遍历
,因此时间复杂度为
。而在计数排序的过程中
用到了长度为
的额外数组
,故空间复杂度为

我们可以看到计数排序突破了基于比较的排序算法效率的下界,达到了线性的复杂度,是到目前为止我们接触到的最快的算法。我们还是可以通过运行时间来间接反应这一结论,大家可以将下面的结果和前面复杂度为

的排序算法进行对比。
>>> python "counting sort.py"
>>> 平均比较次数:0
    平均运行时间:0.0172 s

本节全部代码

← 2-3 树 | 算法与复杂度​zhuanlan.zhihu.com
a39433c575f64974e0d1060db754dbec.png
→ 字符串匹配(TST)| 算法与复杂度​zhuanlan.zhihu.com
a39433c575f64974e0d1060db754dbec.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值