Python集合.计数器:最常见的复杂性

Python集合.计数器:最常见的复杂性,python,time-complexity,counter,python-collections,Python,Time Complexity,Counter,Python Collections,Python中的collections.Counter对象提供的最常见的函数的复杂性是什么 更具体地说,计数器在计数时是否保留某种排序列表,允许它比O(n)更快地执行最常见的操作,当n是添加到计数器的(唯一)项目数时?请注意,我正在处理大量文本数据,试图找到第n个最频繁的标记 我查看了CPython wiki上的和,但找不到答案。准确显示了发生的情况: def most_common(self, n=None): '''List the n most common elements an

Python中的
collections.Counter
对象提供的最常见的
函数的复杂性是什么

更具体地说,
计数器
在计数时是否保留某种排序列表,允许它比
O(n)
更快地执行
最常见的
操作,当
n
是添加到计数器的(唯一)项目数时?请注意,我正在处理大量文本数据,试图找到第n个最频繁的标记

我查看了CPython wiki上的和,但找不到答案。

准确显示了发生的情况:

def most_common(self, n=None):
    '''List the n most common elements and their counts from the most
    common to the least.  If n is None, then list all element counts.

    >>> Counter('abracadabra').most_common(3)
    [('a', 5), ('r', 2), ('b', 2)]

    '''
    # Emulate Bag.sortedByCount from Smalltalk
    if n is None:
        return sorted(self.iteritems(), key=_itemgetter(1), reverse=True)
    return _heapq.nlargest(n, self.iteritems(), key=_itemgetter(1))
heapq.nlargest
是在的源代码中定义的,我们可以看到,如果不指定返回的元素数量,
most_common
将返回计数的排序列表。这是一个
O(n logn)
算法


如果我们使用
most_common
返回
k>1
元素,那么我们使用。这是一个
O(k)+O((n-k)log k)+O(k log k)
算法,对于一个小常数
k
非常好,因为它本质上是线性的。
O(k)
部分来自于对初始
k
计数进行堆化,第二部分来自
n-k
调用
heappushpop
方法,第三部分来自于对
k
元素的最终堆进行排序。由于
k@RomainG,无需担心,如果未指定n,则使用
n log n
,或者使用heapq.nlargest,它是
O(n*log(k))
非常优雅。基准测试证实了这一点:#L=rand_list(10000000)#timeit(lambda:sorted(L)[0:6],number=50)#44.241248495000036#timeit(lambda:heapq.nsmallest(6,L),number=50)#14.2724939099998需要补充的一点是,我们这里只需要一个大小为k的堆!