• 20191104-基于Python计数排序算法分析


    计数排序

    计数排序算法没有用到元素间的比较,它利用元素的实际值来确定它们在输出数组中的位置,也就是说元素从未排序状态变为已排序状态的过程,是由额外空间的辅助和元素本身的值决定的,将每个元素出现的次数记录到辅助空间后,通过对辅助空间内数据的计算,即可确定每一个元素最终的位置,计数排序算法是一个稳定的排序算法。

    算法过程

    1. 根据待排序集合中最大元素和最小元素的差值范围,申请额外空间;
    2. 遍历待排序集合,将每一个元素出现的次数记录到元素值对应的额外空间内;
    3. 对额外空间内数据进行计算,得出每一个元素的正确位置;
    4. 将待排序集合每一个元素移动到计算得出的正确位置上。

    给的无序数组,快速得出其排序结果

    arr=[9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9 ,7,9]

    第一步:求出最大值和最小值,申请额外空间长度等于最大值-最小值+1

    max_val = max(arr)

    #max_val = 10

    min_val = min(arr)

    #min_val = 0

    temp_arr = [0]*(max_val-min_val+1)

    第二步:遍历待排序集合,将每一个元素出现的次数记录到元素值对应的额外空间内

    for i in arr:
        temp_arr[i-min_val]+=1
    print(temp_arr)

    输出结果:

    [1, 2, 1, 3, 2, 2, 1, 2, 1, 4, 1]

    这里为什么是temp_arr[i-min_val],是因为我们要计算一个偏移量,比如对数组【91,92,94,95,92,93排序】,申请的temp_arr初始值为temp_arr = [0,0,0,0,0]

    当遍历到第一个数91的时候,对应的数组下标为91-min_val(91) = 0

    当遍历到第一个数92的时候,对应的数组下标为92-min_val(91) =1

    这个min_val就是偏移量

    第三步:对额外空间内数据进行计算,得出每一个元素的正确位置

    统计数组从第二个元素开始,每一个元素都加上前面所有元素之和。相加的目的,是让统计数组存储的元素值,等于相应整数的最终排序位置。

    for i in range(1,len(temp_arr)):
        temp_arr[i] +=temp_arr[i-1]
    print(temp_arr)

    输出结果:

    [1, 3, 4, 7, 9, 11, 12, 14, 15, 19, 20]

    以i等于3为例:

    次数统计结果为:[1, 2, 1, 3, 2, 2, 1, 2, 1, 4, 1]

    当index=2,temp_arr[index]=1(表示2在待排序列表中出现了1次),待排序列表中比2小的元素个数分别为temp_arr[1]+temp_arr[0]个,所以修改temp_arr[2]=4,以此类推后面的数。比如index = 4的temp_arr[4]=9,表示4最终排序的位置是第9个。

    第四步:将待排序集合每一个元素移动到计算得出的正确位置上

    res = [0]*len(arr)
    for i in range(len(arr)):
        idx = arr[i] - min_val#根据偏移量计算在元素在temp_arr的索引
       
    res[temp_arr[idx]-1] = arr[i]#temp_arr[idx]-1对应为arr[i]在res的位置
       
    temp_arr[idx]-=1
    print(res)

    输出结果

    [0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 9, 9, 10]

    temp_arr[idx]-1对应为arr[i]在res的位置。

    第五步:增加稳定性

    从后向前排序

    res = [0]*len(arr)
    for i in range(len(arr)-1,-1,-1):
        idx = arr[i] - min_val#根据偏移量计算在元素在temp_arr的索引
       
    res[temp_arr[idx]-1] = arr[i]#temp_arr[idx]-1对应为arr[i]在res的位置
       
    temp_arr[idx]-=1
    print(res)

    输出结果

    [0, 1, 1, 2, 3, 3, 3, 4, 4, 5, 5, 6, 7, 7, 8, 9, 9, 9, 9, 10]

    增加稳定性的算法分析

    arr=[9,3,5,4,9,1,2,7,8,1,3,6,5,3,4,0,10,9 ,7,9]。

    1. 遍历第一个元素9,得出元素9的在temp_arr里面的位置temp_arr_index应该是9-min_val = 9
    2. 9在排序后的元素列表的位置是res[temp_arr[temp_arr_index]-1]。其中temp_arr[temp_arr_index]=19此处计算结果为第一个9存放位置为19-1,也就是说res[19-1] = 9 第一个9在res的index=18。
    3. 然后temp_arr[9]-=1得出temp_arr[9]=18
    4. 当我们再次遇到遇到9的话,其位置在res的索引应该是在18-1=17
    5. 。。。。

    得出结论为排序前后值相等的元素前后顺序改变了,不是稳定排序,索引我们应该从后往前遍历,将其修改为稳定排序。

     

    总结-计数排序的优缺点

    1. 当数列最大最小值差距过大时,并不适用计数排序,比如给定20个随机整数,范围在0到1亿之间,这时候如果使用计数排序,需要创建长度1亿的数组。不但严重浪费空间,而且时间复杂度也随之升高。
    2. 如果数列中的元素都是小数,比如25.213,或是0.00000001这样子,则无法创建对应的统计数组。这样显然无法进行计数排序。

    计数排序时间复杂度分析

    假定元素数组长度为n,最大最小差值为m,则:

    1. 代码的第1步涉及求最大最小值时间复杂度为n
    2. 第二步求每个元素的出现次数的时间复杂度为n
    3. 第三步求元素的正确位置的时间复杂度为m
    4. 最后一步排序元素的时间复杂度为n

    所以总体运算量为3n+m,去除常数,时间复杂度为O(n+m)

    原文参考

    https://mp.weixin.qq.com/s/WGqndkwLlzyVOHOdGK7X4Q

    https://www.jianshu.com/p/86c2375246d7

  • 相关阅读:
    50个好用的前端框架,千万收好以留备用!
    嫦娥五号顺利升空,NASA、欧洲航天局回应
    【电脑故障排查】第1章 BIOS和主板故障
    我的老博客——我在chinaunix的家
    Linux操作系统(第二版)(RHEL 8/CentOS 8)
    Java Web整合开发(21) -- 宏观把握Hibernate
    3 远程仓库
    PHP设计模式-策略模式 转
    ubuntu server设置时区和更新时间
    ubuntu 重启 nginx 失败,* Restarting nginx nginx ...fail!
  • 原文地址:https://www.cnblogs.com/hyj691001/p/11792690.html
Copyright © 2020-2023  润新知