看到一个关于二分法查找的Java版本,想看能不能优化一下in_array函数,没想到测试结果要为in_array函数正名。
<?php
class
Test {
/**
* 获取当前时间戳(毫秒级)
*
@return
float
*/
function
microtime_float(){
list($usec, $sec) = explode('
', microtime());
return
((float)$usec + (float)$sec);
}
/**
* 二分法查找
*/
function
binarySearch($ary,$search){
$low = 0;
$high = count($ary)- 1;
while($low <= $high){
$mid = ($low + $high) / 2;
//中间索引
$midVal = $ary[$mid];
//中间元素 猜测的值
if($midVal > $search){
//猜大了
$high = $mid -1;
}else
if($midVal < $search){
//猜小了
$low = $mid +1;
}else{
return
$mid;
//猜到了
}
}
return true;
}
/**
* 冒泡排序
*/
function
sortlist($ary,$order='ASC')
{
for
($i = 0; $i < count($ary); $i++) {//执行count次
for
($j = 0; $j < count($ary)-$i-1; $j++) {
if
($order=='ASC'){
if($ary[$j]>$ary[$j+1]){
//前一个数和后一个数比较
$a = $ary[$j];
$ary[$j] = $ary[$j+1];
$ary[$j+1] = $a;
}
}else{
if($ary[$j]<$ary[$j+1]){
//前一个数和后一个数比较
$a = $ary[$j];
$ary[$j] = $ary[$j+1];
$ary[$j+1] = $a;
}
}
}
}
return
$ary;
}
}
/**
* 数组初始化
*/
$int_arr =
array();
for($i=0; $i<200000; $i++){
// $int_arr[] = $i; // 有序查找 数字型
$int_arr[] =
"{$i}";
// 有序查找 字符串型
// $int_arr[] = rand(0,999999);// 无序查找
}
$int_arr[] = 17985;
$test =
new
Test();
$time_start = $test->microtime_float();
// 具体操作
//方法一 in_array
if(in_array(17985, $int_arr)){
$time_end = $test->microtime_float();
}
//有序数组 : 消耗时间波动在0.00052213668823242~0.00067496299743652之间
//无序数组 : 消耗时间波动在0.0043911933898926~0.0058581829071045之间
//字符数组 : 消耗时间波动在0.0019130706787109~0.0029960735321045之间
//有趣的是 当$i<4000左右的时候,消耗时间会在0.0004和9之间飘动
//方法二 数组key与value翻转,通过isset判断key是否存在于数组中
/* $flipArray = array_flip($int_arr);
if(isset($flipArray[17985])){
$time_end = $test->microtime_float();
} */
//有序数组 : 消耗时间波动在0.028900861740112~0.030332088470459之间
//无序数组 : 消耗时间波动在0.026710033416748~0.030182123184204之间
//字符数组 : 消耗时间波动在0.03516411781311~0.038925955581665之间
//方法三 二分法查找,但二分法只能用于有序查找,在无序时又需要排序算法的支持,因为排序算法在空间和时间复杂度上的不稳定,这里暂时只使用经典冒泡排序法排序测试看看
/* $int_arr = $test->sortlist($int_arr);
if($test->binarySearch($int_arr,17985)){
$time_end = $test->microtime_float();
} */
//有序数组 : 消耗时间波动在4.0054321289062E~5.0067901611328E之间 这个数据时有波动 波动性在0.005和最大9之间,不过出现次数较少,属于不稳定情况:具体是5到6次能出现一次
//无序数组 : 消耗时间波动在 : 超过30秒
echo
'消耗时间:'.($time_end - $time_start);
?>
根据以上结果反应:
在一般情况下in_array函数都是一个最优秀的函数,我的php版本是php-5.5.38,或许在最新的PHP版本里已经调整了in_array的效验机制,说明他的速度已经不比当初了,in_array函数在4000数据量以下,性能是不如方法二的,而且也没有方法二的稳定性,但在大于4000数据量的情况下,in_array函数是优于方法二和方法三的。
稳定性上来说,方法二坚持至终的稳定,没有很快,胜在稳定;
二分法暂时只能猜测他在大数据时候会比较好用吧,但他只能有序数列的查找,感觉应该结合指针和数据库的索引来查找会让他合适