桶排序用于海量数据排序的实验。

刚才在JULY的博客上看了对海量数据排序的讲解(http://blog.csdn.net/v_JULY_v/archive/2011/05/28/6451990.aspx),仔细看了几遍,大概理解了使用归并排序的执行过程。于是想知道如果把归并排序替换成其他方法是否可行。仔细想了一下,觉得桶排序可以一试,所写了程序测试了一下。

 

算法的思路是:

第一步。把每个数据最高的k位作为桶编号,创建2^k个桶.然后把每个数据加入到对应的桶中,因为内存有限,把每个桶与一个文件对应,这样可以得到2^k个文件,由于不同桶中的数据大小已经不同,所以只需要分别把每个桶中的数据排好,那么全部数据就是有序的了。

 

第二步。采用类似计数排序的方法分别对每个文件(桶)中的数据进行排序,由于内存有限不能直接使用计数排序,而是用计数排序的简化版。

 

先用一个数组统计每个数字出现的次数

arr[SIZE]={0};

for each d;

  ++arr[d];

 

然后根据数组中每个元素出现的次数由小到大地输出数据。

for each i in arr

       num=arr[i];

       while num!=0

             print i;          //输出结果

             num=num-1;

 

这样就把一个文件中的数据排好了,分析上面的算法会发现它是 稳定 的排序算法。

 

分析数组arr的大小。

因为数据有10^7个,因此,arr中元素的类型至少应是int类型的,占4个字节。由于内存限制为1M 所以数组arr的大小可取到256k=2^18.

也就是说第一步的每个桶最多只能放2^18个不同的数。题目说每个数字最大为10^7=2^24,因此可以将每个数字的第18~23位作为桶编号,可得64个桶。又因为10^7的二进制形式的第18~23位是100110,转成十进制是38, 即最大的数落在编号为38的桶中。因此实际只需39个桶即可。

 

 

---------------------------------------------------------------------------------------

实验结果:

我在vs2010的release版下测试,所使用的数据是用JULY博客中的给出的随机数生成算法生成的。排序所花的总时间为39秒。

 

又在同样的环境下测试了一下JULY博客中的算法执行时间为:

The time needs in memory sort: 22172ms
The time needs in merge sort: 20344ms

这个算法是按两步分别计时的,所以总时间为42秒。

 

可见两个算法执行时间相似。

 

--------------------------------------------------------------------------------

 

源码:

 

----------------------------------------------------------------------------------------------- 

------------------------------------------------------------------------------------------------

对上面的程序改进了一下,上面的算法保存桶中数据时,存的是整个数字,但实际上数据的高位是不用存的,同一个桶中的数据的高位都是相同的,根据桶的编号就可以把数据的高位部分确定出来。于是我对程序做了修改。

原来的桶文件大小约为2.0M,改进以后每个桶的大小为1.68M,执行时间也有所降低。

改进后的算法的执行时间为28秒

又重复做了几次试验,发现所用时间均为33秒。

-------------------------------------

源码:

 

展开阅读全文

没有更多推荐了,返回首页