算法导论第八章线性时间排序学习总结

本篇博客深入探讨了排序算法的下界,阐述了任何比较排序在最坏情况下的Ω(nlgn)比较次数下限。接着详细介绍了计数排序、基数排序和桶排序这三种线性时间复杂度的排序算法,包括其原理、稳定性以及Python实现。计数排序适用于0到k区间的整数,基数排序则利用数位进行稳定排序,而桶排序假设元素均匀分布在[0,1)区间,适用于均匀分布的数据。" 136796066,5093155,Java中的线程同步与互斥:同步方法与同步块对比,"['java', '多线程', '线程同步']
摘要由CSDN通过智能技术生成

本章围绕四小节展开,第一小节证明任何比较排序在最坏情况下都要经过Ω(nlgn) 次比较,第二、三、四小节分别讨论计数排序、基数排序、桶排序三种线性时间复杂度的排序算法。

排序算法的下界

比较排序算法具备的性质:在排序的最终结果中,各元素的次序依赖于它们之间的比较。
比较排序可以被抽象为一棵决策树,决策树是一棵完全二叉树,它可以表示在给定输入规模情况下,某一特定排序算法对所有元素的比较操作。
定理:在最坏情况下,任何比较排序算法都需要做Ω(nlgn) 次比较。
推论:堆排序和归并排序都是渐进最优的比较排序算法。

计数排序

计数排序:假设n个输入元素中的每一个都是在0到k区间的一个整数,其中k为某个整数。当k=O(n)时,排序运行时间为θ(n)。计数排序是一种稳定的排序算法。
算法思想:对每一个输入元素x,确定小于x的元素个数,利用该信息就可以直接把x放到它在输出数组中的位置。
计数排序代码实现如下:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

class CountingSort:
    def sort(self, A, k):
        C = [0] * (k + 1)
        for j in range(len(A)):
            C[A[j]] = C[A[j]] + 1
        for i in range(1, k + 1):
            C[i] = C[i] + C[i - 1]

        B = [0] * len(A)
        for j in range(len(A) - 1, -1, -1):
            B[C[A[j]] - 1] = A[j]
            C[A[j]] -= 1
        for i in range(len(A)):
            A[i] = B[i]

def test():
    cs = CountingSort()
    A = [2, 5, 3, 0, 2, 3, 0, 3]
    cs.sort(A, 5)
    print(A)

if __name__ == '__main__':
    test()

基数排序

基数排序:按最低有效位进行排序,是一种稳定的排序算法,下图为一组数据的基数排序过程。
在这里插入图片描述
引理:给定n个d位数,其中每一个数位有k个可能的取值,如果基数排序使用的稳定排序方法耗时θ(n+k),那么它就可以在θ(d(n+k))时间内讲这些数排好序。
引理:给定n个b位数和任何正整数r≤b,如果基数排序使用的稳定排序算法对数据取值区间是0到k的输入进行排序耗时θ(n+k),那么它就可以在θ((b/r)(n+2^r))时间内讲这些数排好序。
基数排序代码实现如下:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

class RadixSort:
    def sort(self, A, d):
        temp = A.copy()
        for i in range(d):
            temp = [t // 10 for t in temp]
            self.__count_sort(A, 9, temp)

    def __count_sort(self, A, k, B):
        keys = [num % 10 for num in B]
        C = [0] * (k + 1)
        for j in range(len(keys)):
            C[keys[j]] = C[keys[j]] + 1
        for i in range(1, k + 1):
            C[i] = C[i] + C[i - 1]
        tempA = [0] * len(A)
        tempB = [0] * len(B)
        for j in range(len(A) - 1, -1, -1):
            tempA[C[keys[j]] - 1] = A[j]
            tempB[C[keys[j]] - 1] = B[j]
            C[keys[j]] -= 1
        for i in range(len(A)):
            A[i] = tempA[i]
            B[i] = tempB[i]

def test():
    rs = RadixSort()
    A = [329, 457, 657, 839, 436, 720, 355]
    rs.sort(A, 3)
    print(A)

if __name__ == '__main__':
    test()

桶排序

桶排序:假设输入是由一个随机过程产生,该过程将元素均匀、独立地分布在[0,1)区间上,桶排序将区间划分为n个相同大小的子区间,即桶,之后将n个输入数分别放到各个桶中。若假设输入输入数据服从均匀分布,平均情况下它的时间代价为O(n) 。桶排序是稳定的排序算法。
桶排序代码实现如下:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

class BucketSort:
    def sort(self, A):
        import math
        n = len(A)
        B = []
        for i in range(n):
            B.append([])
        for i in range(n):
            B[math.floor(n * A[i])].append(A[i])
        for i in range(n):
            B[i].sort()

        i = 0
        for j in range(n):
            for num in B[j]:
                A[i], i = num, i + 1

def test():
    bs = BucketSort()
    A = [0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68]
    bs.sort(A)
    print(A)

if __name__ == '__main__':
    test()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值