php算法 - 二分查找 2019-09-23

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

    查找过程:

    首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

    算法要求:

    1.必须采用顺序存储结构

    2.必须按关键字大小有序排列。


    其实,说白了 ,就是当我们有一个这样的数组[1,5,9,10,11,16,23,25,31,35,48,52,56,59,60,67];

    我们要找出某个值的位置时,例如16在哪个位置时,应该如何快速找到他?如果从头往后找,或者从尾往前找,是不是很慢?如果数组N长,我们的查找就有可能是N次。

    而二分查找就不一样了。

    直接折半。比如上面例子数组有16个元素。 16/2=8那就是从 arr[8] 这个位置开始找。首先我们判断16是否等于 arr[8]这个值 如果等于返回,不等于则判断是否大于/小于 ,如果大于,则往上找,小于则往下找。

    按照上面例子。

    像上面例子,找到为16的过程仅仅只有 3次就能找到。如果我们仅仅使用循环,则要循环到第6次才能真正找到他的位置。


    OK,我们贴代码(我上的是递归版,循环版的大家可以自行模仿写一个,也可以百度查找demo)


    /**
     * 
     * @param array $container 数组
     * @param type $search要找的数据
     * @param type $low 开始位置
     * @param type $top结束位置
     * @return string 返回 如果找到则是位置的key,如果没找到则是返回没找着哦
     */
    function BinaryQueryRecursive(array $container, $search, $low = 0, $top = 'default') {
    
        $top == 'default' && $top = count($container);
        if ($low <= $top) {
            $mid = intval(floor($low + $top) / 2);
            if (!isset($container[$mid])) {
                return '没找着哦';
            }
            if ($container[$mid] == $search) {
                return $mid;
            }
            if ($container[$mid] < $search) {
                return BinaryQueryRecursive($container, $search, $mid + 1, $top);
            } else {
                return BinaryQueryRecursive($container, $search, $low, $mid - 1);
            }
        }
    }
    
    $container = [1, 5, 9, 10, 11, 16, 23, 25, 31, 35, 48, 52, 56, 59, 60, 67];
    echo BinaryQueryRecursive($container, 16);



    给大家个图自己看看逻辑是这样的,例子显示搜39,第一次是蓝色这条的搜索,第二次是橙色,第三次绿色。三次完成。

    u=684932595,3038379881&fm=26&gp=0.jpg