查詢演算法之二分法
-
二分法查詢的前提是待找的陣列是一個有序的陣列(這裡假設陣列是一個從小到大的陣列)
-
遞迴的查詢需要找到的值
-
思路:首先是一個有序的陣列,找到這個陣列的中間值,然後需要找到的值和這個中間值比較,如果是比中間值小,就向右遞迴,否則向左遞迴
-
陣列
$arr = [2, 36, 25, 1, -1, 45, 99];
-
待找到的值
-1
<?php
/**
* Notes:
* File name:${fILE_NAME}
* Create by: Jay.Li
* Created on: 2019/12/11 0011 17:00
*/
class dichotomy
{
public function searchValue(array $data, int $leftIndex, int $rightIndex, int $findValue)
{
if (!is_array($data)) {
return ['message' => '非陣列', 'status' => 0];
}
$middleIndex = floor(($leftIndex + $rightIndex) / 2);//中間值的鍵
$middleValue = $data[$middleIndex];//中間值
/**
* 遞迴結束條件
*/
if ($leftIndex > $rightIndex) {
return -1;
}
if ($findValue > $middleValue) {
return $this->searchValue($data, $middleIndex + 1, $rightIndex, $findValue);
} elseif ($findValue < $middleValue) {
return $this->searchValue($data, $leftIndex, $middleIndex - 1, $findValue);
} else {
return $middleIndex;
}
}
}
$obj = new dichotomy();
//$data = [2, 36, 25, 1, -1, 45, 99];
$data = [20,50,60,70,80,90,100,280,290,390,490,490,590,690,790,890,990,1000,10101,1000000];
var_dump($obj->searchValue($data, 0, count($data) - 1, 590));
上述的二分查詢法還有一定的侷限性,當它找到某個需要的值的時候,就會直接返回,如果有需要得到所有相同的鍵,目前就不滿足了,所以現在需要這樣:
<?php
/**
* Notes:
* File name:${fILE_NAME}
* Create by: Jay.Li
* Created on: 2019/12/11 0011 17:00
*/
class dichotomy
{
public function searchValue2(array $data, int $leftIndex, int $rightIndex, int $findValue)
{
if (!is_array($data)) {
return ['message' => '非陣列', 'status' => 0];
}
$arr = [];
$middleIndex = floor(($leftIndex + $rightIndex) / 2);//中間值的鍵
if ($middleIndex < $leftIndex || $middleIndex > $rightIndex) {
return ['message' => sprintf("該 [%d] 值不在陣列內", $findValue), 'status' => 0];
}
$middleValue = $data[$middleIndex];//中間值
/**
* 遞迴結束條件
*/
if ($leftIndex > $rightIndex) {
return $arr[] = -1;
}
if ($findValue > $middleValue) {
return $this->searchValue2($data, $middleIndex + 1, $rightIndex, $findValue);
} elseif ($findValue < $middleValue) {
return $this->searchValue2($data, $leftIndex, $middleIndex - 1, $findValue);
} else {
$tempLeft = $middleIndex - 1;
while (true) {
//向左迴圈,得到所有相同的鍵
if ($tempLeft < $leftIndex || $data[$tempLeft] != $middleValue) {
//迴圈退出的條件,當鍵值越界或者是下一個值和中間值找到的值不相等,退出
break;
}
array_push($arr, $tempLeft);
$tempLeft--;
}
array_push($arr, $middleIndex);
$tempRight = $middleIndex + 1;
while (true) {
//向右迴圈,得到所有相同的鍵
if ($tempRight > $rightIndex || $data[$tempRight] != $middleValue) {
break;
}
array_push($arr, $tempRight);
$tempRight++;
}
return $arr;
}
}
}
try {
$obj = new dichotomy();
//$data = [2,3,5,8,8,8, 45, 99];
$data = [20,50,60,70,80,90,100,280,290,390,490,490,590,590,590,590,590,690,790,890,990,1000,10101,1000000];
var_dump($obj->searchValue2($data, 0, count($data) - 1, 100000011));
var_dump($obj->searchValue2($data, 0, count($data) - 1, 590));
} catch (\Exception $e) {
var_dump($e->getMessage());
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結
LIYi ---- github地址