[英]How can I implement binary search in Perl?
我想在Perl中实现二进制搜索算法。 我的'数组'按递减顺序排序(不是实际数组,而是获取索引并返回值的函数)。 问题是可能存在一系列相同的值。 如果我的搜索值在这样的范围内,我想返回包含它的第一个索引。
这就是我写的:
# get_val should be a *decreasing* function for idexes $i in min..max,
# formally: for any $i,$j s.t. $max>=$i>$j>=$min :
# $get_val_subref($i, $extra) <= $get_val_subref($j, $extra)
# min and max are the inclusive boundaries for the search
# get_val sub should get an index in min..max and an extra data reference, and return
# the value for the given index
# returns the smallest index $i in min..max for which $get_val_subref($j, $extra)
# returns $searched_val, or undef if no such index exists
sub binary_search {
my ( $min, $max, $searched_val, $get_val_subref, $get_val_sub_extra_data )
= @_;
my ( $mid, $val );
while ( $min <= $max ) {
$mid = $min + int( ( $max - $min ) / 2 );
$val = $get_val_subref->( $mid, $get_val_sub_extra_data );
if ( $val > $searched_val ) {
$min = $mid + 1;
}
elsif ( $val < $searched_val ) {
$max = $mid - 1;
}
else { ## SEE MY QUESTION BELOW ##
# surely $val == $searched_val, but is it the first one?
if ( $mid > $min
and $get_val_subref->( $mid - 1, $get_val_sub_extra_data )
== $searched_val )
{
# $val == $searched_val and prev($val) == $searched_val
# we have to continue
$max = $mid - 1;
}
else {
# $val == $searched_val and prev($val) != $searched_val
# wer'e done
return $mid;
}
}
}
# $val was not found. return undef
return undef;
}
这是一个使用它的简单示例:
sub get_val_sub {
my ( $pos, $a ) = @_;
my $val = $a->[$pos];
return $val;
}
my @arr = (80, 40, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
say "RET:", binary_search( 0, $#arr, 0, \&get_val_sub, \@arr );
问题是我不确定我的最后一个(标有## SEE MY QUESTION BELOW ##
)是“漂亮的”。 有没有更好的方法呢?
虽然我最初同意Axeman的答案......但是,它在某种程度上类似于我使用线性逻辑(至少一小部分)的第一个(非常糟糕的)答案。 具体来说,没有理由用$mid - 1
调用$get_val_subref
。 这是一个不必要的线性搜索步骤。
这是我的建议。 除了避免线性搜索,它还具有非常简单的优点:
sub binary_search {
...
my ( $mid, $val, $solution );
while ( $min <= $max ) {
...
else {
$solution = $mid; # Store a possible solution.
$max = $mid - 1; # But continue with the binary search
# until $min and $max converge on each other.
}
}
return $solution;
}
虽然我第一次同意FM的答案,但你所展示的情况(全部为零)并不是线性反向搜索的好例子。 虽然我不喜欢你只需继续二进制搜索,“第X” 确实有可计算的价值, 仍然有子线性的性能,而线性回搜索有-当然-是线性的。
所以我喜欢你的想法,但它更像这样紧凑:
else {
return $mid unless
( $mid > $min
and $get_val_subref->( $mid - 1, $get_val_sub_extra_data )
== $searched_val
);
$max = $mid - 1;
}
线性反向搜索是一种更容易的计算,但随着值函数变得越来越复杂,计算越少越好。
你可能正在寻找牛顿的近似方法 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.