二分查找

二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

算法要求

1、必须采用顺序存储结构。
2、必须按关键字大小有序排列。

算法步骤

其实,二分查找也还是比较容易理解的,大概就是一分为二,然后两边比较,保留有效区间,继续一分为二查找,直到找到或者超出区间则结束,所以二分查找的基本步骤是:

1、确定要查找的区间
2、确定要二分时的参照点
3、区间内选取二分点
4、根据二分点的值,综合左右区间情况以及求解的目的,舍去一半无用的区间
5、继续在有效区间重复上面的步骤

代码示例

这里主要用非递归和递归两种实现方式查找,代码如下:

1、非递归查找

/*    * 二分查找(也叫折半查找)--非递归    * array $arr 待查找区间    * int $number 查找数    * int 返回找到的键     */    public function binarySearch($arr,$number){                 //待查找的区间不为数组或为空,则返回-1        if(!is_array($arr) || empty($arr)){            return -1;        }        sort($arr); //二分查找关键点        $len=count($arr);        $lower=0;        $high=$len-1;        //低点小于高点,则退出        while($lower<=$high){            //以中间点作为参照点比较            $middle=intval(($lower+$high)/2);            if($arr[$middle]>$number){                //查找数比参照值小,舍去右边                $high=$middle-1;            }else if($arr[$middle]<$number){                //查找数比参照值大,舍去左边                $lower=$middle+1;            }else{                //查找数与参照点相等,则返回                return $middle;            }        }        return -1;    }

2、递归查找

/*    * 二分查找(也叫折半查找)--递归    * array $arr 待查找区间    * int $number 查找数    * int $lower  低点    * int $high   高点    */    public function binarySearchRecursion($arr,$number,$lower,$high)    {            //待查找区间如果不是数组或为空,返回-1        if(!is_array($arr) || empty($arr)){            return -1;        }        sort($arr);        $len=count($arr);        $middle=intval(($lower+$high)/2);        if($arr[$middle]>$number){            //查找数比参照值小,舍去右边            return $this->binarySearchRecursion($arr,$number,0,$middle-1);        }elseif($arr[$middle]<$number){            //查找数比参照值大,舍去左边            return $this->binarySearchRecursion($arr,$number,$middle+1,$high);        }else{            //查找数与参照值相等,则返回            return $middle;        }        //找不到,则返回-1        return -1;    }

算法使用

需求是在待查找区间$arr中,找出$number所在的位置,调用算法如下:

//待查找区间的数组$arr=array(1,2,3,4,5,6,7,10,12,14,18,16,20);//非递归查找$arr中25所在的位置$binaryKey=$this->binarySearch($arr,25);//递归查找$arr中12所在位置$binarySearchRecursionKey=$this->binarySearchRecursion($arr,1,12,count($arr)-1); //打印输出 print_r($binaryKey); echo '//'; print_r($binarySearchRecursionKey);
输出结果-1//8

时间复杂度分析

在有序数组中如果用暴力的算法去查找,也就是逐个遍历比较,那么时间复杂度是O(n);但是,用二分查找后,因为每次可以舍去一半查找区间,所以会将时间复杂度减少到O(logn),算法更优。 (关于算法的时间复杂度与空间复杂度详细解释)

相关资料

PHP算法之二分查找