मैं पर्ल में एक बाइनरी खोज एल्गोरिदम लागू करना चाहता हूं। मेरा 'सरणी' घटते क्रम में क्रमबद्ध होता है (वास्तविक सरणी नहीं, बल्कि एक फ़ंक्शन जो इंडेक्स प्राप्त करता है और मान देता है)। समस्या यह है कि समान मूल्यों का विस्तार हो सकता है। यदि मेरा खोज मूल्य इस तरह के खिंचाव में है, तो मैं इसे शामिल करने वाली पहली अनुक्रमणिका वापस करना चाहता हूं।मैं पर्ल में बाइनरी खोज कैसे कार्यान्वित कर सकता हूं?
यह मैं क्या लिखा है:
# 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 ##
के साथ चिह्नित नहीं कर रहा हूँ है) सुंदर है"। क्या ऐसा करने का कोई बेहतर तरीका है?