这是我最喜欢的算法之一,用于在非常大的数组中快速查找所需内容。它是我创建并广泛使用于 PHP 代码中的
二分查找算法 实现。它绝对比直接迭代搜索例程更有效。您可以以多种方式变化它以适应您的需要,但基本算法保持不变。
要使用它(这个变体),数组必须按照您想要查找的索引进行排序,按从低到高的顺序。
function quick_find(&$array, $property, $value_to_find, &$first_index) {
$l = 0;
$r = count($array) - 1;
$m = 0;
while ($l <= $r) {
$m = floor(($l + $r) / 2);
if ($array[$m]->{$property} < $value_to_find) {
$l = $m + 1;
} else if ($array[$m]->{$property} > $value_to_find) {
$r = $m - 1;
} else {
$first_index = $m;
return $array[$m];
}
}
return FALSE;
}
并进行测试:
class test_object {
public $index;
public $whatever_you_want;
public function __construct( $index_to_assign ) {
$this->index = $index_to_assign;
$this->whatever_you_want = rand(1, 10000000);
}
}
$my_array = array();
$my_index = rand(1256, 30000);
$index_to_locate = $my_index + rand(200, 30234);
for ($i = 0; $i < 1000000; $i++) {
$searchable_object = new test_object($my_index);
array_push($my_array, $searchable_object);
$my_index++;
}
echo "Searching array of ".count($my_array)." objects for index: " . $index_to_locate ."\n\n";
$index_found = -1;
$object = quick_find($my_array, "index", $index_to_locate, $index_found);
if ($object == NULL) {
echo "Index $index_to_locate was not contained in the array.\n";
} else {
echo "Object found at index $index_found!\n";
print_r($object);
}
echo "\n\n";
现在,有几点需要注意:
您可以使用此方法查找非唯一索引;但是数组必须按升序排序。然后,当它找到符合您条件的元素时,您必须向后遍历数组以找到第一个元素,或向前遍历以找到最后一个元素。这将增加一些搜索的时间,但仍然比迭代大型数组要快。
对于字符串索引,您可以将quick_find()中的算术比较(即“>”和“<”)更改为PHP的函数“strcasecmp()”。只需确保字符串索引按照相同方式排序(例如实现示例):按字母顺序和升序排列。
如果您想要一个版本,可以搜索按升序或降序排序的对象数组:
function quick_find_a(&$array, $property, $value_to_find, &$first_index) {
$l = 0;
$r = count($array) - 1;
$m = 0;
while ($l <= $r) {
$m = floor(($l + $r) / 2);
if ($array[$m]->{$property} < $value_to_find) {
$l = $m + 1;
} else if ($array[$m]->{$property} > $value_to_find) {
$r = $m - 1;
} else {
$first_index = $m;
return $array[$m];
}
}
return FALSE;
}
function quick_find_d(&$array, $property, $value_to_find, &$first_index) {
$l = 0;
$r = count($array) - 1;
$m = 0;
while ($l <= $r) {
$m = floor(($l + $r) / 2);
if ($value_to_find > $array[$m]->{$property}) {
$r = $m - 1;
} else if ($value_to_find < $array[$m]->{$property}) {
$l = $m + 1;
} else {
$first_index = $m;
return $array[$m];
}
}
return FALSE;
}
function quick_find(&$array, $property, $value_to_find, &$first_index) {
if ($array[0]->{$property} < $array[count($array)-1]->{$property}) {
return quick_find_a($array, $property, $value_to_find, $first_index);
} else {
return quick_find_d($array, $property, $value_to_find, $first_index);
}
}