为什么在计数排序算法中不能使用哈希表/字典?

时间:2018-12-16 16:15:34

标签: python python-3.x algorithm sorting hash

使用计数排序算法时,将创建一个列表,并使用其索引作为键,同时将整数出现的次数添加为列表中的值。为什么这与简单地创建一个以keys作为索引并以counts作为值的字典不同?如:

hash_table = collections.Counter(numList) 

hash_table = {x:numList.count(x) for x in numList} 

创建哈希表后,基本上只需将整数出现的次数复制到另一个列表中即可。哈希表/字典的查找时间为O(1),因此如果您仅引用键/值对,为什么这不是首选?

我将下面的计数排序算法包括在内以供参考:

def counting_sort(the_list, max_value):
    # List of 0's at indices 0...max_value
    num_counts = [0] * (max_value + 1)

    # Populate num_counts
    for item in the_list:
        num_counts[item] += 1

    # Populate the final sorted list
    sorted_list = []

    # For each item in num_counts
    for item, count in enumerate(num_counts):

        # For the number of times the item occurs
        for _ in xrange(count):

            # Add it to the sorted list
            sorted_list.append(item)

    return sorted_list

1 个答案:

答案 0 :(得分:4)

您当然可以做这样的事情。问题是这样做是否值得。

计数排序的运行时间为O(n + U),其中n是数组中元素的数量,U是最大值。请注意,随着U变得越来越大,该算法的运行时间开始明显下降。例如,如果U> n并且我在U上再增加一位(例如,将其从1,000,000更改为10,000,000),则运行时间可以增加十倍。这意味着随着U变得越来越大,计数排序开始变得不切实际,因此通常在U相当小时运行计数排序。如果您要使用较小的U值进行排序排序,那么使用散列表不一定是值得的。散列项比仅进行标准阵列查找要花费更多的CPU周期,对于小型阵列而言,潜在的内存节省可能不值得花费额外的时间。而且,如果您使用非常大的U值,则最好切换到基数排序,这实际上是许多较小的计数排序,而U的值很小。

另一个问题是,计数排序的重组步骤具有惊人的引用局部性-您只需在counts数组和输入数组中并行填充值即可进行扫描。如果您使用哈希表,则会失去某些局部性,因为哈希表中的元素不一定是连续存储的。

但是,这些是更多的实现参数。从根本上说,计数排序与“使用数组”无关,而与“构建频率直方图”有关。正好是在构建直方图时,常规的旧数组通常比哈希表更可取。