在系统中,我们经常会遇到这样的需求:将大量(比如几十万、甚至上百万)的对象进行排序,然后只需要取出最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有类似的最小堆结构,但是当我们需要处理更复杂的问题时,可能依然需要自己定制。

关于topN问题的几种解决方案的更多相关文章

  1. PHP中实现MySQL嵌套事务的两种解决方案

    PHP中实现MySQL嵌套事务的两种解决方案 一.问题起源 在MySQL的官方文档中有明确的说明不支持嵌套事务: Transactions cannot be nested. This is a co ...

  2. zepto的tap事件的点透问题的几种解决方案

    你可能碰到过在页面上创建一个弹出层,弹出层有个关闭的按钮,你点了这个按钮关闭弹出层后,这个按钮正下方的内容也会执行点击事件(或打开链接).这个被定义为这是一个“点透”现象. 以前,我也听到过tap的点 ...

  3. Mybatis多参传递的四种解决方案

    Mybatis多参传递的四种解决方案 代码异常:org.apache.ibatis.binding.BindingException: Parameter 'param' not found. 长时间 ...

  4. javascript文件夹选择框的两种解决方案

    javascript文件夹选择框的两种解决方案 解决方案1:调用windows 的shell,但会有安全问题. * browseFolder.js * 该文件定义了BrowseFolder()函数,它 ...

  5. bugfree如何修改Bug7种解决方案的标注方法

    Bug有7种解决方案的标注方法 By Design- 就是这么设计的,无效的Bug Duplicate - 这个问题别人已经发现了,重复的Bug External - 是个外部因素(比如浏览器.操作系 ...

  6. [转]ArcGIS移动客户端离线地图的几种解决方案

    原文地址:http://blog.chinaunix.net/uid-10914615-id-3023158.html 移动GIS中,通常将数据分为两大类:basemap layer和operatio ...

  7. Hibernate懒加载的三种解决方案

    Hibernate懒加载的两种解决方案: 1.Hibernate.initialize(代理对象) 2.在*.hbm.xml映射文件中添加lazy="false"属性 3.使用op ...

  8. 探讨SQL Server并发处理存在就更新七种解决方案

    前言 本节我们来讲讲并发中最常见的情况存在即更新,在并发中若未存在行记录则插入,此时未处理好极容易出现插入重复键情况,本文我们来介绍对并发中存在就更新行记录的七种方案并且我们来综合分析最合适的解决方案 ...

  9. ASP.NET实现在线浏览Word文档另一种解决方案(Word转PDF)

    ASP.NET实现在线浏览Word文档另一种解决方案(Word转PDF)      上述博文里提到的在线浏览pdf的方案不错,但word转pdf的那个dll只支持doc不支持docx,附上最新的下载链 ...

随机推荐

  1. MapReduce 框架原理

    1. Hadoop 序列化 1.1 自定义Bean对象实现序列化接口 必须实现 Writable 接口: 反序列化时,需要反射调用空参构造函数,所以必须有空参构造: 重写序列化方法: 重写反序列化方法 ...

  2. fzu1704(高斯消元法解异或方程组+高精度输出)

    题目链接:https://vjudge.net/problem/FZU-1704 题意:经典开关问题,求使得灯全0的方案数. 思路:题目保证至少存在一种方案,即方程组一定有解,那么套上高斯消元法的板子 ...

  3. [转帖]Windows安全认证是如何进行的?[Kerberos篇]

    Windows安全认证是如何进行的?[Kerberos篇] NTLM 的简单看了一下 基本上了解了.. 这个KERBEROS 的看不太懂 感觉说的我也有点迷糊.. 虽然是对称加密的 但是不清不楚的.. ...

  4. Linux Centos下软件的安装与卸载方法

    转载于: http://blog.csdn.net/zolalad/article/details/11368879 Linux下软件的安装与卸载   第一章   linux下安装软件,如何知道软件安 ...

  5. java--键盘输入任意数字进行求和

    思路,我将键盘输入的数放入数组,然后便利数组进行求和 package com.test.day01; import java.util.Scanner; public class Test { pub ...

  6. (MVC — — Demo)客户管理系统的开发日志

    点击一下 目录 第一步:搭建开发环境 第二步:层次包(按照三层架构思想写) 第四步:开发(utils)工具包 第四步:开发 Dao 层 第五步:开发 services 层 第六步:开发 factory ...

  7. B - How many integers can you find

      Now you get a number N, and a M-integers set, you should find out how many integers which are smal ...

  8. QAbstractItemModel使用样例与解析(Model::index使用了createIndex,它会被销毁吗?被销毁了,因为栈对象出了括号就会被销毁)

    参考:qt源码 qstandarditemmodel_p.h qstandarditemmodel.h qstandarditemmodel.cpp qabstractitemmodel.h qabs ...

  9. [http]HTTP请求过程

    我们在浏览器输入http://www.baidu.com想要进入百度首页,但是这是个域名,没法准确定位到服务器的位置,所以需要通过域名解析,把域名解析成对应的ip地址,然后通过ip地址查找目的主机.整 ...

  10. gulp 实现sass自动化 ,监听同步

    实现功能 监听scss文件 sass自动化 准备条件 1 .安装gulp npm init   ---->一直enter,会在当前目录下生成一个package.json文件,记录安装的依赖模块 ...