【发布时间】:2016-07-08 18:26:45
【问题描述】:
我对以下结果有点困惑,我希望你们中的一些人能够阐明为什么线性搜索似乎比 Perl 中的二进制和插值更快。
Benchmark: timing 1000000 iterations of Binary, Interpolation, Linear...
Binary: 17 wallclock secs (16.33 usr + 0.00 sys = 16.33 CPU) @ 61236.99/s (n=1000000)
Interpolation: 4 wallclock secs ( 3.65 usr + 0.00 sys = 3.65 CPU) @ 273972.60/s (n=1000000)
Linear: 2 wallclock secs ( 1.52 usr + 0.00 sys = 1.52 CPU) @ 657894.74/s (n=1000000)
每个功能如下。我正在尝试编写一堆众所周知的算法,并在使用 Perl 掌握算法中进行后续操作。
sub LinearSearch {
# Search linearly for a value
my $val = $_[0];
my $arrptr = $_[1];
for (my $i=0; $i<ARR_LENGTH; ++$i) {
if ($arrptr->[$i] == $val) {
return $i;
}
}
return -1;
}
sub BinarySearch {
my $val = $_[0];
my $arrptr = $_[1];
my $low = 0;
my $high = ARR_LENGTH; # to be modified
while ($low <= $high) {
my $middle = int(($low + $high) / 2);
my $midValue = $arrptr->[$middle];
if ($midValue < $val) {
$low = $middle + 1;
} elsif ($midValue > $val) {
$high = $middle - 1;
} else {
return $middle;
}
}
return -1;
}
sub InterpolationSearch {
my $val = $_[0];
my $arrptr = $_[1];
my $low = 0;
my $high = ARR_LENGTH; # to be modified
while ($val >= $arrptr->[$low] && $val <= $arrptr->[$high]) {
# solve for the middle value again
my $middle = int($low + ($high - $low)*(($val - @{$arrptr}[$low])
/ (@{$arrptr}[$high] - @{$arrptr}[$low] + 1)));
my $middleVal = $arrptr->[$middle];
if ($middleVal < $val) {
$low = $middle + 1;
} elsif ($middleVal > $val) {
$high = $middle - 1;
} else {
return $middle;
}
}
return -1; # Not found
}
另外,ARR_LENGTH 定义为
use constant ARR_LENGTH => 10_000;
一开始。奇怪的是,二进制搜索需要这么长时间,然后插值更少,但仍然是线性搜索的两倍。
基准代码(就是我在网上找到的):
my @array = OrderedArray();
my $random_val = $array[int(rand(ARR_LENGTH))];
timethese(1_000_000, {
Interpolation => 'InterpolationSearch($random_val, \@array)',
Binary => 'BinarySearch($random_val, \@array)',
Linear => 'LinearSearch($random_val, \@array)' }
);
OrderedArray() 只是一个快速(可能不必要)的功能
sub OrderedArray {
# Create a random ordered array
my @arr;
for (my $i=1; $i<=ARR_LENGTH; ++$i) {
push @arr, $i;
}
return @arr;
}
【问题讨论】:
-
我从不查看没有生成它们的代码的基准。太容易出错了。请出示您的代码。
-
提示:
ARR_LENGTH应该是@$arrptr -
你的数组排序了吗?您是否计算了算法循环内发生的迭代次数?您是否在二分搜索之前对每次迭代都调用排序?
-
您还需要显示基准测试代码。基准测试的一个常见错误是在每次迭代后更改数据而不恢复数据。
-
@JayKumarR 真的吗?我已经在我的机器上多次运行了这段代码,每一个都与上面的相似......