二分查找又称折半查找,只对有序的数组有效。
优点是比较次数少,查找速度快,平均性能好,占用系统内存较少;
缺点是要求待查表为有序表,且插入删除困难。
因此,折半查找方法适用于不经常变动而查找频繁的有序列表。
 
一、算法思想
首先,将表中间位置记录的值与查找值比较,如果两者相等,则查找成功;否则利用中间位置将表分成前、后两个子表,如果中间位置的值大于查找值,则进一步查找前一子表,否则进一步查找后一子表。
重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。
具体做法如下:
(1) 将数组的第一个位置设置为下边界(0)。
(2) 将数组最后一个元素所在的位置设置为上边界(数组的长度减 1)。
(3) 若下边界等于或小于上边界,则做如下操作:
a. 将中点设置为floor((上边界+下边界)/2)。
b. 如果中点的元素小于查询的值,则将下边界设置为中点元素所在下标加1。
c. 如果中点的元素大于查询的值,则将上边界设置为中点元素所在下标减1。
d. 否则中点元素即为要查找的数据,可以进行返回。
 
二、PHP的二分查找算法实现
1、递归方式
// 数组为升序排序
function binarySearch($arr, $search) {
    $start = 0;
    $end = count($arr) - 1;
    while ($start <= $end) {
        $mid = floor(($start + $end) / 2);
        // echo "当前的中点:" . $mid;   // 用于显示每次重新计算后得到的中点
        if ($search == $arr[$mid]) {
            return $mid;
        } elseif ($search < $arr[$mid]) { // 所查值小于中间值,则在$mid左边的值中查找
            $end = $mid - 1;
        } else { // 所查值大于中间值,则在$mid右边的值中查找
            $start = $mid + 1;
        }
    }
    return -1; // 查找失败
}
2、非递归方式
// 数组为升序排序
function binSearch($arr, $start, $end, $search) {
    if ($start <= $end) {
        $mid = floor(($start + $end) / 2);
        if ($search == $arr[$mid]) {
            return $mid;
        } elseif ($search < $arr[$mid]) {
            return binSearch($arr, $start, $mid - 1, $search);
        } else {
            return binSearch($arr, $mid + 1, $end, $search);
        }
    }
    return -1;
}
 
三、计算连续重复次数
function countDuplicate($arr, $search) {
    $count = 0;
    $position = binarySearch($arr, $search);
    if ($position > -1) {
        $count++;
        for ($i = $position - 1; $i > 0; $i--) {
            if ($arr[$i] == $search) {
                $count++;
            } else {
                break;
            }
        }
        for ($i = $position + 1; $i < count($arr); $i++) {
            if ($arr[$i] == $search) {
                $count++;
            } else {
                break;
            }
        }
    }
    return $count;
}
 
// 测试
$arr = array(1, 2, 4, 4, 4, 39, 4, 4, 4, 4, 78, 33, 69);
$cnt = countDuplicate($arr, 4);
echo $cnt;    // 4
我们可以看到,示例中数组有3个连续的4和4个连续的4,而结果为4。
这是因为这个函数一开始调用 binSearch( ) 函数来查找指定的值。如果在数组中能找到这个值,这个函数就通过两个循环来统计这个值连续重复出现的次数。
第一个循环向下遍历数组,统计找到的值出现的次数,当下一个值与要查找的值不匹配时则停止计数。
第二个循环向上遍历数组,统计找到的值出现的次数,当下一个值与要查找的值不匹配时则停止计数。

数据结构与算法之PHP查找算法(二分查找)的更多相关文章

  1. Java中常用的查找算法——顺序查找和二分查找

    Java中常用的查找算法——顺序查找和二分查找 神话丿小王子的博客 一.顺序查找: a) 原理:顺序查找就是按顺序从头到尾依次往下查找,找到数据,则提前结束查找,找不到便一直查找下去,直到数据最后一位 ...

  2. 递归分治算法之二维数组二分查找(Java版本)

    [java] /** * 递归分治算法学习之二维二分查找 * @author Sking 问题描述: 存在一个二维数组T[m][n],每一行元素从左到右递增, 每一列元素从上到下递增,现在需要查找元素 ...

  3. C语言查找算法之顺序查找、二分查找(折半查找)

    C语言查找算法之顺序查找.二分查找(折半查找),最近考试要用到,网上也有很多例子,我觉得还是自己写的看得懂一些. 顺序查找 /*顺序查找 顺序查找是在一个已知无(或有序)序队列中找出与给定关键字相同的 ...

  4. 【算法训练营day1】LeetCode704. 二分查找 LeetCode27. 移除元素

    [算法训练营day1]LeetCode704. 二分查找 LeetCode27. 移除元素 LeetCode704. 二分查找 题目链接:704. 二分查找 初次尝试 看到题目标题是二分查找,所以尝试 ...

  5. 【PHP数据结构】线性查找与二分查找

    欢迎来到查找的世界,在学习完各种数据结构之后,总算走到了这一步,不知道大家有什么感想呢?反正我是边学边忘,现在让我去说说图的那几个算法还是在蒙圈的状态中.不过学习嘛,就是一步一步的来,暂时搞不懂的东西 ...

  6. List<T>线性查找和二分查找BinarySearch效率分析

    今天因为要用到List的查找功能,所以写了一段测试代码,测试线性查找和二分查找的性能差距,以决定选择哪种查找方式. 线性查找:Contains,Find,IndexOf都是线性查找. 二分查找:Bin ...

  7. Java顺序查找、二分查找

    Java顺序查找.二分查找   查找算法中顺序查找算是最简单的了,无论是有序的还是无序的都可以,只需要一个个对比即可,但其实效率很低. 顺序查找 动图演示 详细代码 // 顺序查找 public st ...

  8. Java基础知识强化60:经典查找之二分查找

    1. 二分查找       二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好:其缺点是要求待查表为有序表,且插入删除困难.因此,折半查找方法适用于不经常变动而查找频繁的有序列表. 比较 ...

  9. 【Java数据结构与算法】简单排序、二分查找和异或运算

    简单排序 选择排序 概念 首先,找到数组中最小的那个元素,其次,把它和数组的第一个元素交换位置(如果第一个元素就是最小的元素那么它就和自己交换).再次,在剩下的元素中找到最小的元素,将它与数组的第二个 ...

  10. 各种查找算法的选用分析(顺序查找、二分查找、二叉平衡树、B树、红黑树、B+树)

    目录 顺序查找 二分查找 二叉平衡树 B树 红黑树 B+树 参考文档 顺序查找 给你一组数,最自然的效率最低的查找算法是顺序查找--从头到尾挨个挨个遍历查找,它的时间复杂度为O(n). 二分查找 而另 ...

随机推荐

  1. 3、使用keepalived高可用LVS实例演示

    回顾: keepalived: vrrp协议的实现: 虚拟路由器: MASTER,BACKUP VI:Virtual Instance keepalived.conf GLOBAL VRRP LVS ...

  2. js,jq获取父,兄弟,子节点整理

    js获取节点 父: parentNode 获取已知节点的父节点. 子: childNodes; 得到全部子节点 children 得到全部子节点 firstChild 获得第一个子节点 lastChi ...

  3. python shelve模块

    #coding=utf- import shelve f = shelve.open("shelve_test") f['info'] = "alex" f[, ...

  4. sqlserver 中通配符%和_的使用

    --以a开头的数据 SELECT * FROM BCUSTOMER_MZN WHERE CST_NAME LIKE 'A%' --以Z结尾的数据 SELECT * FROM BCUSTOMER_MZN ...

  5. jmeter5.0之源码导入 IntelliJ IDEA

    IDEA 编译 Jmeter 1.下载并解压 jmeter 源码 http://archive.apache.org/dist/jmeter/source/ 下载源码后解压『Jmeter』,我这边下载 ...

  6. [转][C++]佛祖保佑,永无bug。C++ BUG解决方案

    // // _oo0oo_ // o8888888o // 88" . "88 // (| -_- |) // 0\ = /0 // ___/`---'\___ // .' \\| ...

  7. ABP的配置 请求类型

    1.ServerRootAddress 项目运行的根地址   需要跟启动项目配置的地址相同 2.CorsOrigins 允许哪些地址访问 不会出现跨域 启动项目配置的地址

  8. IPC 之 Messenger 的使用

    一.概述 Messenger 是一种轻量级的 IPC 方案,它的底层实现是 AIDL ,对 AIDL 进行了封装,方便了对它的使用.Messenger 一次只处理一个请求,所以在服务端不用考虑线程同步 ...

  9. Java之——利用Comparator接口对多个排序条件进行处理

    转载自:http://blog.csdn.net/l1028386804/article/details/56513205 膜拜大神··· 一.需求 假设现在有个如此的需求:需要对一个这样的雇员列表进 ...

  10. 学习笔记54—均方误差(MSE)和均方根误差(RMSE)和平均绝对误差(MAE)

    https://blog.csdn.net/reallocing1/article/details/56292877 MSE: Mean Squared Error  均方误差是指参数估计值与参数真值 ...