算法导论学习笔记(二)排序和顺序统计量

本文深入讲解了多种排序算法,包括堆排序、快速排序等高级排序方法。探讨了它们的时间复杂度、空间复杂度及实现细节。此外,还介绍了线性时间排序算法如计数排序、基数排序和桶排序的工作原理及其应用场景。

总结各种排序算法,时间复杂度与空间复杂度,优缺点等。

堆排序

堆排序的时间复杂度是θ(nlogn)θ(nlog⁡n),堆排序具有空间原址性。

堆是一个数组,可以看成一棵近似的完全二叉树。除了最底层之外,该树完全填满,给定一个节点i,可以很容易地计算其父节点为floor(i/2),左子节点为2i,右子节点为2i+1.

最大堆是指堆中最大元素存在于根节点。根节点的值大于等于子节点。

建立堆

堆排序:建立最大堆,然后把根元素与最后一个元素交换位置,再把节点n去掉,并使得剩余n-1个节点重新满足最大堆。重复此过程,则将按照从大到小的顺序依次把元素从堆中取出。从而完成排序。

快速排序

快排平均时间复杂度是θ(nlogn)θ(nlog⁡n),最坏时间复杂度是θ(n2)θ(n2)

但是快排通常是实际应用中最好的选择,原因如下:

  • 原址排序
  • 平均性能非常好,虽然平均时间复杂度是θ(nlogn)θ(nlog⁡n),但是常数因子小得多

快排:在数组中随机找到一个元素,交换数组中其他元素的位置,使得该元素左边的数都比他小,右边的数都比他大。递归调用。

从快排的原理,易知其平均时间复杂度是θ(nlogn)θ(nlog⁡n),在最坏的情况下,相当于插入排序,因此时间复杂度是θ(n2)θ(n2)

# -*- coding: utf-8 -*-

# 原址重排
def partition(A, p, r):
    # 选择一个元素,然后把比他小的放在数组的左边,把比他大的放在数组的右边
    x = A[r]
    # 用i,j分表指向左边的子数组的终点、右边的子数组的终点
    i = p - 1
    j = p
    while j < r:
        if A[j] <= x:
            i += 1
            tmp = A[i]
            A[i] = A[j]
            A[j] = tmp
        j += 1
    # 交换
    A[r] = A[i + 1]
    A[i + 1] = x
    return i + 1

def quicksort(A, p, r):
    '''

    :param A: 数组
    :param p: 数组的起点下标
    :param r: 数组的终点下标
    :return:
    '''
    if p < r:
        q = partition(A, p, r)
        quicksort(A, p, q - 1)
        quicksort(A, q+1, r)

if __name__ == '__main__':
    A = [2,8,7,1,3,5,6,4]
    quicksort(A, 0, len(A)-1)
    print A

快排的随机化版本

为了增加随机性,使得划分更加均匀,每次随机从数组中挑选一个元素作为划分节点。

线性时间排序

所有基于比较的排序方法的时间复杂度的上界是θ(nlogn)θ(nlog⁡n)。存在其他不适基于比较的排序算法,可以达到线性时间复杂度。

计数排序

假设n个输入元素的每一个都是在0-k之间的一个整数。时间复杂度为θ(n)θ(n)

计数排序的过程是:对每个输入的元素,都统计比它小的元素的个数。这样就可以直接把它在输出数组的位置上插入。当有几个元素相同时要稍作修改。
计数排序是稳定的。

基数排序

基数排序是指先按照最低有效位进行排序来解决卡片排序问题。之所以先按照最低有效位排序,是因为高位比低位优先级要高。为了确保基数排序的有效性,一位数排序算法必须是稳定的。

应用:

用基数排序来对具有多个关键字域的记录进行排序。

桶排序

假设数据服从均匀分布。

桶排序将[0,1)区间划分成n个大小相同的区间,称为桶。然后把n个输入分别放到各个桶中。再对各个桶的数据排序。

因为数据是均匀分布的,所以不会出现很多数据落在同一个桶的情况。

中位数和顺序统计量

最大值、最小值:因为每个元素都需要比较,所以时间复杂度为θ(n)θ(n)

中位数和顺序统计量:时间复杂度也为θ(n)θ(n)。思想类似于快排。只不过只处理递归划分的一边即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值