在系统中,我们经常会遇到这样的需求:将大量(比如几十万、甚至上百万)的对象进行排序,然后只需要取出最Top的前N名作为排行榜的数据,这即是一个TopN算法。常见的解决方案有三种:

(1)直接使用List的Sort方法进行处理。

(2)使用排序二叉树进行排序,然后取出前N名。

(3)使用最大堆排序,然后取出前N名。

   第一种方案的性能是最差的,后两种方案性能会好一些,但是还是不能满足我们的需求。最主要的原因在于使用二叉树和最大堆排序时,都是对所有的对象进行排序,而不是将代价花费在我们需要的少数的TopN上。对于堆结构来说,并不需要你获取所有的数据,只需要对前N个数据进行处理。因此可以通过堆栈的进入排出,用小顶堆实现,调整最小堆的时间复杂度为lnN,总时间复杂度为nlnN

myheap:

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


# 最小堆化heap
def siftdown(heap, start, end):
while True:
left_child = start * 2 + 1
if left_child > end:
break
if left_child + 1 <= end:
if heap[left_child] > heap[left_child+1]:
left_child += 1

if heap[left_child] < heap[start]:
heap[left_child], heap[start] = heap[start], heap[left_child]
start = left_child
else:
break


def minheapstyle(heap):
first = len(heap) // 2 - 1
for x in xrange(first, -1, -1):
siftdown(heap, x, len(heap)-1)


def push(heap, item):
heap.append(item)
minheapstyle(heap)


def pushpop(heap, item):
if heap[0] < item:
heap[0] = item
minheapstyle(heap)


if __name__ == '__main__':
heap = [10,4,5,3,5,6,2]
minheapstyle(heap)
print heap
TOPN:
import myheap


def findminn(list, n):
heap = []
for x in list:
if len(heap) < n:
myheap.push(heap, x)
else :
myheap.pushpop(heap, x)
return heap


if __name__ == '__main__':
l = [5,6,7,8,9,10,5646]
#n=5
heap = findminn(l,5)
print heap

虽然python有类似的最小堆结构,但是当我们需要处理更复杂的问题时,可能依然需要自己定制。