zoukankan      html  css  js  c++  java
  • 详解计数排序

    相较于冒泡排序,快速排序他们之间都是基于元素之间的比较来进行排序的。
    而计数排序可以做到线性的时间复杂度,是由于它是利用数组下标来确定元素的正确位置的。
    那么如何利用数组下标来确定元素位置呢?
    给定一个20个整数的无序数列,取值范围是0-10,所以就可以创建一个长度为11的数组。然后开始遍历这个无序的随机数列,每一整数按照其值对号入座,这时在这个创建的数组上对应其值的下标的元素加1.
    有点绕,就是假设20个整数中有3个9,那么我们就找到那3个9,并在对应数组的索引的元素上加1.所以创建的数组元素的索引9上的元素是3。
    最终,当这个无序数列遍历完毕之后,该数组中每一个下标位置的值代表数列中对应整数出现的次数。
    有了这个统计就可以直接遍历数组,输出数组下标的值(索引),元素的值是几,就输出几次。
    这里需要编写的操作主要有

    1.确定数组的长度

    max_value = array[0]
        for i in range(1, len(array)):
            if array[i] > max_value:
                max_value = array[i]
    

    先假设列表中第一个元素最大,然后遍历列表,比较找出最大的那个值
    然后根据这个值创建数组

    count_array = [0] * (max_value+1)
    

    2.遍历数列,填充统计数组(这也是最重要的一步)

        for i in range(0, len(array)):
            count_array[array[i]] += 1 
    

    这里用数列的值当做索引,然后再加1.若一个数列中相同的值很多,那么就会继续加1

    3.遍历统计数组,输出结果

    sorted_array = []
        for i in range(0, len(count_array)):
            for j in range(0, count_array[i]):
                sorted_array.append(i)
        return sorted_array
    

    这里创建个数组来接收排序后的列表,利用count_array[i]这个代表无序数列中具体的元素有几个来进行for循环。可以精确的输出元素有几个。

    这样输出该数组就达到了计数排序的目的了

    但这里还有些优化的点。比如,
    1.我们无法确定输出相同值元素原本在无序数列中的顺序,这就造成这是个不稳定排序
    2.创建数组的长度是根据无序数列中最大元素确定的,这个其实是不可取的。如:99,100,22,33,4,5.这6个元素组成的无序数列,按最大元素就要创建100个下标的数组,这太浪费空间了。
    对于第1点优化的点可以采用从统计数组的第二个元素开始,每个元素都加上前面所有元素之和。
    对于第2点优化可以采用max_value-min_value+1得出数组的长度,但这其实还是比较浪费空间(这里其实可以去看看堆排序,他在创建数组空间上做的比较好)

    完整代码(优化的计数排序)

    # 计数排序的优化属于稳定版本的计数排序,可以返回相同数据的顺序先后;可用在学生成绩排名
    def count_sort_v2(array=[]):
        # 1.得到数列的最大值最小值,并算出差值d
        max_value = array[0]
        min_value = array[0]
        for i in range(1, len(array)):
            if array[i] > max_value:
                max_value = array[i]
            if array[i] < min_value:
                min_value = array[i]
        d = max_value - min_value
        # 2.创建统计数组并统计对应元素个数
        count_array = [0] * (d+1)
        for i in range(0, len(array)):
            count_array[array[i]-min_value] += 1 # 这里创建的统计数组全为0
        # 3.统计数组做变形,后面的元素等于前面的元素之和
        for i in range(1, len(count_array)):
            count_array[i] += count_array[i-1] # 这算个列表的技巧,后面索引的值是前面索引值的和
        # 4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
        sorted_array = [0] * len(array)
        for i in range(len(array)-1, -1, -1): # array[i]是原数组的值
            # 这里减1是为啥,因为数组是从0开始的
            sorted_array[count_array[array[i]-min_value]-1] = array[i] # count_array[array[i]-min_value]填充统计数组的值,min_value是统计数组的开头
            count_array[array[i] - min_value] -= 1
        return sorted_array # 返回的是重新创建的数组,这里创建了2个数组
    
    
    my_array = list([4, 4, 6, 5, 3, 2, 8, 1, 7, 5, 6, 0, 10])
    print(count_sort(my_array))
    my_array = list([95, 94, 91, 120, 90, 99, 93, 91, 92])
    print(count_sort_v2(my_array))
    
    
    努力拼搏吧,不要害怕,不要去规划,不要迷茫。但你一定要在路上一直的走下去,尽管可能停滞不前,但也要走。
  • 相关阅读:
    php中的md5()的安全问题
    爆破之中文转换成字母脚本
    MYSQL数据库封装类
    SQL执行结果操作
    原生和jquery 的 ajax
    Ajax实例OR技术原理 转自 (http://blog.csdn.net/evankaka )
    JQuery常用事件
    分页原理
    JQuery中$.ajax()方法参数
    session和cookie的作用和原理
  • 原文地址:https://www.cnblogs.com/wkhzwmr/p/15344768.html
Copyright © 2011-2022 走看看