编程之美读书笔记_2.5 寻找最大的K个数

2.5 寻找最大的K个数

n个数中寻找最大的k个数,

两种思路:

1 保存目前找到的最大k个数,每访问一个数,就与这k个数中的最小值比较,决定是否更新这k个数。储存k个数的数据结构可采用:败者树、二叉查找树、最小堆。

C++ STL提供了multisetpriority_queue容器,另外还提供了make_heappush_heappop_heap方便手动构建堆结构。(测试发现,手工建堆的效率最高,当nk增大到一定值时,采用红黑树的multiset的效率极差。手动建堆的效率相比priority_queue,有略微提高。)

 

2 修改排序方法,去除不必要的过程。

选择排序: 只要选k次。

冒泡排序: 只要冒泡k次即可。

堆排序:   构建好最大堆后,取 k次最大值

快速排序: 分区时,根据数P将数组分为两部分,设大于P的数个数为a,小于P的数的个数为b。如果,a>=k,则从这a个数取最大的k个数,若a<k,则从b个数取最大的k-a-1个。

归并排序: 当待合并的两个数组,两数组长度和大等于k时,合并时只取前k个。或者:以(k+1)/2个数为一组,将数组分成几个组,对每组进行排序(可以采用任何一种高效的排序方法)后,两两合并时只取前k个。

计数排序: 如果都是整数,先扫描一遍找出最大值max,最小值min,再扫一遍,将每个值减去min,对这个值计数,最后从max-min开始统计,找出最大的k个数。另外,也可采用桶排序。


桶排序:   可以不对桶内的数据进行排序。 具体例子

基数排序: 可以采用最高关键字比较方法,并免去相关的排序。

 

STL中的nth_element就是基于对intorsort的修改(introtsort是对快速排序的改进,当递归深度达到一定值时,可切换到堆排序),而partial_sortpartial_sort_copy是基于堆排序的修改,因而在k很小时,其效率可能会高于nth_element。遗憾的是:STL没有提供完全基于堆排序的nth_element

 

从下面的测试结果,可以看出:在M不是很大,M/N很小时,partial_sortpartial_sort_copy尽管多了“对堆结构进行排序”这个不必要的操作,其效率仍然高于nth_element,但相差不多。而在其它情况下nth_element的效率则比其它的几种方法要高很多。

如果源数据都是整数,多数情况下(即使允许修改源数据),桶排序方法(结合计数方法)的效率比nth_element高。桶排序只需256K的内存,效率很高。在MN至少有一个大于当前内存大小的情况下,桶排序是最佳选择,其性能远高于其它方法。

 

测试结果说明:测试程序要求不得改变源数据,某些方法要多一个复制源数据操作,可以从partial_sort_copypartial_sort效率的差异,看出这个复制操作的影响。桶排序方法对应nth_count;对堆结构的调整,采用三种途径(分别对应三个程序):利用push_heappop_heap、只用pop_heap、手写代码调整。(测试了几次,multisetheapsort方法,在相同NM情况下,所用时间起伏很大,即所用时间对原始数据依赖性很高。)

测试代码

 

N,M: 1000000 800000    0.8

Randomizing: 78 ms

nth_elmemnt  16  ms

nth_count  16  ms

priority_queue  47  ms

partial_sort  125  ms

partial_sort_copy  110  ms

heap(pop/push)   31  ms

heap(pop/copy)  32  ms

heap(custom_pop)  31  ms

multiset  484  ms

heap_sort  172  ms

 

 

N,M: 100000000 10000    0.0001

Randomizing: 5453 ms

nth_elmemnt  1828  ms

nth_count  750  ms

priority_queue  406  ms

partial_sort  844  ms

partial_sort_copy  328  ms

heap(pop/push)   203  ms

heap(pop/copy)  375  ms

heap(custom_pop)  391  ms

multiset  375  ms

heap_sort  4015  ms

 

 

N,M: 100000000 10000    0.0001

Randomizing: 5454 ms

nth_elmemnt  1796  ms

nth_count  766  ms

priority_queue  391  ms

partial_sort  843  ms

partial_sort_copy  344  ms

heap(pop/push)   188  ms

heap(pop/copy)  375  ms

heap(custom_pop)  390  ms

multiset  375  ms

heap_sort  4016  ms

 

 

N,M: 100000000 100000    0.001

Randomizing: 5453 ms

nth_elmemnt  1719  ms

nth_count  750  ms

priority_queue  406  ms

partial_sort  844  ms

partial_sort_copy  343  ms

heap(pop/push)   187  ms

heap(pop/copy)  375  ms

heap(custom_pop)  391  ms

multiset  438  ms

heap_sort  4234  ms

 

 

N,M: 100000000 100000    0.001

Randomizing: 5438 ms

nth_elmemnt  1719  ms

nth_count  750  ms

priority_queue  406  ms

partial_sort  860  ms

partial_sort_copy  343  ms

heap(pop/push)   203  ms

heap(pop/copy)  360  ms

heap(custom_pop)  390  ms

multiset  438  ms

heap_sort  4078  ms

 

 

N,M: 100000000 1000000    0.01

Randomizing: 5453 ms

nth_elmemnt  1735  ms

nth_count  765  ms

priority_queue  438  ms

partial_sort  1125  ms

partial_sort_copy  515  ms

heap(pop/push)   204  ms

heap(pop/copy)  406  ms

heap(custom_pop)  422  ms

multiset  1031  ms

heap_sort  4797  ms

 

 

N,M: 100000000 1000000    0.01

Randomizing: 5453 ms

nth_elmemnt  1797  ms

nth_count  781  ms

priority_queue  454  ms

partial_sort  1140  ms

partial_sort_copy  531  ms

heap(pop/push)   204  ms

heap(pop/copy)  406  ms

heap(custom_pop)  437  ms

multiset  1032  ms

heap_sort  4828  ms

 

 

N,M: 100000000 5000000    0.05

Randomizing: 5469 ms

nth_elmemnt  1781  ms

nth_count  782  ms

priority_queue  610  ms

partial_sort  1953  ms

partial_sort_copy  3578  ms

heap(pop/push)   344  ms

heap(pop/copy)  593  ms

heap(custom_pop)  578  ms

multiset  3641  ms

heap_sort  9391  ms

 

 

N,M: 100000000 5000000    0.05

Randomizing: 5469 ms

nth_elmemnt  1750  ms

nth_count  797  ms

priority_queue  625  ms

partial_sort  1953  ms

partial_sort_copy  3562  ms

heap(pop/push)   344  ms

heap(pop/copy)  578  ms

heap(custom_pop)  578  ms

multiset  3625  ms

heap_sort  9406  ms

 

 

 

 

你可能感兴趣的:(数据结构,编程,c,测试,读书,360)