我正在尝试对数组执行二进制搜索。我需要找到一个值应放置在数组中以保持顺序的位置。我可以找到很多帖子,它们在搜索现有值,但不一定在寻找不存在值的正确位置。我需要它来处理偶数或奇数长度的数组。
$vals= [1,2,4,6,7,9,13];
$test_1 = 5; // should return 3
$test_2 = 10; // should return 6
function mySearch(array $array, $start, $end, $value){
if($end<$start){return false;}
$mid = floor(($end + $start)/2);
while($mid != $value){
if($mid > $value){
return mySearch($array, $start, $mid-1, $value);
}elseif($mid < $value){
return mySearch($array, $mid+1, $end, $value);
}
}
echo $mid;
}
答案 0 :(得分:1)
我相信,您可以通过验证要搜索的左侧和右侧的值来实现此目的,就像这样:
function mySearch(array $array, $start, $end, $value) {
if ($end < $start){
return false;
}
$index = floor(($end + $start)/2);
$indexValue = $array[$index];
// edge case when the value already exists on the array
if ($indexValue == $value) {
return $index;
}
// test the value on the left side when value for the current index is greater
// than the value being searched
$previousIndex = $index - 1;
if (
$value < $indexValue
&& (
$previousIndex < 0 // edge case when there's no more values on the left side
|| $array[$previousIndex] <= $value
)
) {
return $index;
}
// test the value on the right side when value for the current index is greater
// than the value being searched
if ($value > $indexValue) {
$nextIndex = $index + 1;
if ($nextIndex > $end || $array[$nextIndex] >= $value) {
return $nextIndex;
}
// edge case when the value would be appended to the array
if ($nextIndex + 1 > $end) {
return $nextIndex + 1;
}
}
// normal binary search logic
if ($indexValue < $value) {
return mySearch($array, $index, $end, $value);
} else {
return mySearch($array, $start, $index, $value);
}
}
我已经编写了此方法来验证它是否有效:
$testValues = range(0, 15);
$vals = [1,2,4,6,7,9,13];
foreach ($testValues as $value) {
if (in_array($value, $vals)) {
continue;
}
$index = mySearch($vals, 0, count($vals) - 1, $value);
echo "For value: {$value} index: {$index} Array: " . printArray($vals, $index, $value);
}
function printArray(array $values, int $index, int $value) : string {
$toPrint = [];
$isAdded = false;
foreach ($values as $i => $val) {
if (!$isAdded && $i >= $index) {
$toPrint[] = "({$value})";
$isAdded = true;
}
$toPrint[] = $val;
}
if (!$isAdded) {
$toPrint[] = "({$value})";
}
return "[" . implode(", ", $toPrint) . "]\n";
}
输出为:
For value: 0 index: 0 Array: [(0), 1, 2, 4, 6, 7, 9, 13]
For value: 3 index: 2 Array: [1, 2, (3), 4, 6, 7, 9, 13]
For value: 5 index: 3 Array: [1, 2, 4, (5), 6, 7, 9, 13]
For value: 8 index: 5 Array: [1, 2, 4, 6, 7, (8), 9, 13]
For value: 10 index: 6 Array: [1, 2, 4, 6, 7, 9, (10), 13]
For value: 11 index: 6 Array: [1, 2, 4, 6, 7, 9, (11), 13]
For value: 12 index: 6 Array: [1, 2, 4, 6, 7, 9, (12), 13]
For value: 14 index: 7 Array: [1, 2, 4, 6, 7, 9, 13, (14)]
For value: 15 index: 7 Array: [1, 2, 4, 6, 7, 9, 13, (15)]