二进制搜索数组中的正确位置

时间:2019-09-18 14:52:01

标签: php

我正在尝试对数组执行二进制搜索。我需要找到一个值应放置在数组中以保持顺序的位置。我可以找到很多帖子,它们在搜索现有值,但不一定在寻找不存在值的正确位置。我需要它来处理偶数或奇数长度的数组。

$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;

}

1 个答案:

答案 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)]