我必须对一些整数进行排序,这些整数的值可以在30.000.000到350.000.000之间。整数将在0到65.535之间,平均计数为20.000。 RAM的使用是无关紧要的,速度只是重要的。
稍后,我还必须将它们分成组,只要这些值中的两个之间的差距> 65.535,就必须设置除法,这就是我需要的算法。
如果它有任何区别,该算法将用于Perl脚本。
编辑:经过深思熟虑并阅读答案后,我意识到了一些事情:我实际上并不关心数据本身。因为我真的只想找到间隙小的组的起始值和结束值,所以排序只需要创建存储桶并且可以丢弃数据。
Edit2:经过一些测试并尝试了所提供的答案后,我发现的最快方式是:
my @sort = sort {$a <=> $b} @item_offsets;
my @buckets;
my $start = shift @sort;
push @buckets, [$start,$start];
for my $item ( @sort ) {
if ( $item < $buckets[$#buckets][1]+$gap ) {
$buckets[$#buckets][1] = $item;
}
else {
push @buckets, [$item,$item];
}
}
say $#buckets;
答案 0 :(得分:17)
你不太可能在Perl中编写一个比Perl的内置sort
函数更好的排序算法:
@numbers = sort {$a <=> $b} @numbers;
您可以尝试使用sort pragma来查看特定算法是否更好:
use sort '_quicksort';
use sort '_mergesort';
由于您的切割点会因数据分布而异,我认为您需要先对整个列表进行排序,然后循环切割它以进行切割。
my $prev = shift @numbers; # already sorted
my @group = [$prev];
my $i = 0;
foreach my $n (@numbers) {
$i++ if ($n - $prev > 65535);
push @{$group[$i]}, $n;
$prev = $n;
}
答案 1 :(得分:17)
我在运行算法之前只生成一个桶数组,每组包含65536个连续值。存储桶将包含其内容的最小值和最大值,但不会存储内容本身。运行算法后,对存储桶执行一次传递。如果有两个连续的非空桶,其中min(bucket2)-max(bucket1)&lt; 65536,结合它们。在算法完成运行之前不会发生组合。丢弃任何空桶。该算法是线性时间。
记下Bucket Sort。
答案 2 :(得分:12)
我使用基数排序,因为你需要对输出进行分组。
答案 3 :(得分:5)
我只是说radix sort,http://en.wikipedia.org/wiki/Radix_sort但是这可能比你想要实现的要高一些,Introsort通常是数据http://en.wikipedia.org/wiki/Introsort的公认排序解决方案,它是一个变体快速排序,当它达到较小的集合时切换到堆栈,因为它在较小的集合上比快速排序更快。
答案 4 :(得分:1)
我会试试这个:
my @sorted = map { unpack "N" } sort map { pack "N" } @unsorted;
答案 5 :(得分:0)
如果您使用数字作为数组的索引,然后递增该位置的计数,您已将它们“分组”,并在一次传递中完成。
伪代码中的:
while(morenumbers)
sorted[[unsorted[number]]++
number++
如果提前知道范围,您可以减少索引值(例如,值-30000以使其进入正确的范围)。