海量数据取中位数,比较简单耗时的是用堆排序
2012-10-15 15:13
232 查看
海量数据取中位数
分类: 算法2012-05-1120:35 68人阅读 评论(0) 收藏 举报
转自:http://hi.baidu.com/mxp446533129/blog/item/a6025efa293f1c00d9f9fdaf.html
若有很大一组数据,数据的个数是N(每个数占4个字节),内存大小为M个字节,其中M<4*N,使得不能在现有内存情况下通过直接排序找到这N个数的中位数。解决海量数据中取中位数的方法有两种比较简单耗时的是用堆排序,还有一种是改造后基于段的计数:
1)分区间堆排序:
在现有M大小内存情况下若最多能够造出包含p个数据的堆,则先扫描一次这N个数据找到最小的p个数,耗时O(Nlog(p)),设这p个数中最大的数是a,将堆清空,在第二轮扫描出比a大的中最小的p个数,然后在把a改为记录这p个数中最大的数,依次类推,直到计算到某一轮p个数和之前够造出的数的个数大于N/2,在这p个数中找到所有数中的中位数,耗时的地方是每轮扫描构建堆都要用了O(Nlog(p)),构造的次数为N/(2*p),所以它的时间复杂度是O(N*N*log(p)/(2*p)).
2)基于段的计数
基于段的计数指的的是对一个区间范围的计数,与计数排序不同的是后者对每一个数出现次数的计数,而前者是对出现在某一区间范围内的数计数,段的大小取决于内存大小和每段计数器所占的字节数,而计数器大小又受总数据量有关,需满足计数器的最大计数能够大于最大个数N,比如本题中内存大小是M个字节,而N的大小至少需要用logN位来表示,设k个字节表示的无符号整数可以最大值大于N,则放在内存中计数器个数是M/k,设q=M/k,即这N个数分为q个段,每一段的大小是n=N/q,第一段数的范围是0~n-1,第二段是n~2*n-1,依此类推。现在我们可以从硬盘中逐个扫面这N个数,根据每个数的大小来修改他们对应范围的计数器,需要用O(N)时间完成对这q个段的计数。然后从第一段开始往后扫描累加每个段的计数器,直到累加到某一段的计数器使得它和这之前的个数大于N/2,假设这个段所表示的范围是q~q+n-1,那么这N个数的中位数就在q~q+n-1这个范围内,现在更改计数器的属性不在基于段而是基于每个数,且只针对q~q+n-1这n个数计数,还需要一轮扫面N个数来完成对n个计数器的确定,在本段之前的段计数器计数之和是t,t<2/N,那么只要依次从新的n个计数器开始累加到s,使得满足t+s>N/2那一个计数器,它所代表的数就是这N个数的中位数。
分享到:
上一篇:双层桶划分
下一篇:hash
相关文章推荐
- 6种排序算法及其比较 简单选择排序,堆排序,简单插入排序,希尔排序,冒泡排序,快速排序,归并排序
- ThreadPoolTaskExecutor 多线程分解执行耗时任务与单线程串行执行简单比较
- ThreadPoolTaskExecutor 多线程分解执行耗时任务与单线程串行执行简单比较
- 快速排序、堆排序、归并排序简单比较
- ThreadPoolTaskExecutor 多线程分解执行耗时任务与单线程串行执行简单比较
- 堆排序 合并排序 快速排序 简单比较
- 你知道的,javascript语言的执行环境是"单线程模式",这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行,因此很多时候需要进行“异步模式”,请列举js异步编程的方法。
- 比较简单的将数据信息导入wrod文档方案(C# for word)
- Windows下比较简单的获取网页源码的方法
- SDUT-1333 简单字符串比较
- 分享一个比较简单的canvas+js 飞翔的小鸟小游戏
- php+mysql中存储过程性能简单比较
- 看看一个朋友写的代码,大家发表发表意见,比较简单的代码
- 文件比较工具-BCompare的简单使用
- 程序员必知的8大排序(二)-------简单选择排序,堆排序(java实现)
- ZOJ 3489题解 此题比赛是木有做出来,想的方法太复杂,最后看别人的方法与自己的比较才明白可以如此简单,只需计算被2整除的次数就行了!哎,方法很重要啊!
- 【笔试面试】简单总结笔试和面试中的海量数据问题
- 解决Wince 设备连接SQL数据库时耗时比较久
- 编译BaseClasses,该工程是对dshow的一个简单封装, 据说用它开发比较方便。
- 几种web矢量图形的简单性能比较(2)