美文网首页数据结构和算法分析PHP经验分享PHP开发
【查找算法】二分查找/插值查找/斐波那契查找(PHP)

【查找算法】二分查找/插值查找/斐波那契查找(PHP)

作者: Bryanz | 来源:发表于2022-01-29 09:30 被阅读0次

除了排序,查找指定值也是常见的功能,所以非常有必要掌握一下相关算法。经典查找算法有顺序查找二分查找差值查找斐波那契查找。顺序查找比较简单就不介绍了,下面主要介绍剩余三种查询算法的实现原理PHP代码示例,以及性能分析
<输入的最好方式就是输出>,本着学习的态度表达一下自己浅显的理解。

1.二分查找
二分查找算法的实现前提是待排数组必须是有序的(以下算法均以升序为例),其主要思想是通过将每次取数组中间位置作为比较对象,小于该位置则到左区间寻找,大于该位置则到右区间寻找,左右区间按照同样的方式,循环取当前区间中间值比较,直到找到最终结果。

代码如下:

function binarySearch(array $arr, int $val)
{
    $len = count($arr);
    $left = 0;//初始区间左下标
    $right = $len - 1;//初始区间右下标
    $result = -1;
    //越界处理
    if ($val > $arr[$right] || $val < $arr[$left]){
        return $result;
    }
    //边界处理
    if ($arr[$left] == $val){
        return $left;
    }elseif ($arr[$right] == $val){
        return $right;
    }else{
        //开始二分查找
        while ($left <= $right) {
            $mid = $left + intval(($right - $left) / 2);//取中间值
            if ($arr[$mid] == $val) {
                return $mid;//返回待查值下标位置
            } elseif ($arr[$mid] > $val) {
                //值在左边
                $right = $mid - 1;
            } else {
                //值在右边
                $left = $mid + 1;
            }
        }
    }
    return $result;//未找到
}

记忆关键词:区间二分
性能分析:时间复杂度O(logn)

2.插值查找
插值查找是二分查找的优化,区别在于:二分查找每次与中间位置进行比较,而插值查找每次与最靠近待查值的位置进行比较,比盲目的二分策略性更强。

代码如下:

function interpolationSearch(array $arr, int $val)
{
    $len = count($arr);
    $left = 0;
    $right = $len - 1;
    $result = -1;
    //边界处理
    if ($val < $arr[$left] || $val > $arr[$right]) {
        return $result;
    }
    while ($left < $right) {
        $mid = $left + abs(($val - $arr[$left]) * ($right - $left) / ($arr[$right] - $arr[$left]));//注意绝对值
        $mid = intval($mid);
        if ($arr[$mid] == $val) {
            return $mid;//返回元素下标
        } elseif ($arr[$mid] > $val) {
            //左侧
            $right = $mid - 1;
        } else {
            //右侧
            $left = $mid + 1;
        }
    }
    return -1;//未找到
}

插值查询的关键在于mid的确定,根据下图等式可得到mid的值

1-mid公式

记忆关键词: 差值比例
性能分析:时间复杂度O(logn)

3.斐波那契查找
斐波那契查找算法是斐波那契数列的应用,斐波那契数列又称黄金分割数列,其核心公式为F(n)=F(n-1)+F(n-2),即从第三项开始,每一项可以分割为前一项和前两项之和,而前一项与当前项的比值接近0.618,该比例称为黄金分割比例,斐波那契查找算法的核心思想就是将数组按照黄金分割比例进行查找划分。代码实现思路:

  • 构造斐波那契数列
  • 找到大于等于数组长度的最小值k,即F(k)>=len
  • 最大值填充数组多余长度
  • 按照黄金分割比例进行查找
  • 若未找到,根据差值进入左右分区,左分区长度为F(k-1)右分区为F(k-2)
  • 在新的分区重复黄金分割比例查找,直到找到结果或未找到结果。

代码如下:

/**
 * 获取斐波那契数列值
 * F(1)=F(2)=1,F(k)=F(k-1)+F(k-2),k>=3
 * @param int $k
 * @return int|void
 * @throws Exception
 */
function fioNum(int $k = FIBONACCI_NUM)
{
    if ($k < 1) {
        throw new Exception('k必须为大于0的整数');
    }
    if ($k == 1 || $k == 2) {
        return 1;//数列初始值
    }
    return fioNum($k - 1) + fioNum($k - 2);
}
/**
 * 斐波那契查找
 * @param array $arr
 * @param int $val
 * @return bool|int|mixed
 * @throws Exception
 */
function fibSearch(array $arr, int $val)
{
    $len = count($arr);
    //数组长度小于3,直接用顺序查找
    if ($len < 3) {
        foreach ($arr as $k => $v) {
            if ($v == $val) {
                return $k;
            }
        }
        return -1;
    }
    $left = 0;
    $right = $len - 1;
    $fibArr = [];//斐波那契数列
    $k = 0;//斐波那契数列最小值初始化
    try {
        //1.构造斐波那契数列
        $fibNum = 0;
        while ($len > $fibNum) {
            //2.寻找大于等于数组长度的最小值k
            $k++;
            $fibNum = fioNum($k);
            $fibArr[] = $fibNum;
        }
    } catch (Exception $e) {
        throw new Exception($e->getMessage());
    }
    //3.对多余部分进行最大值填充
    for ($i = $len - 1; $i < $fibNum; $i++) {
        $arr[$i] = $arr[$right];
    }
    $k--;//数组下标从0开始,所以要减1
    //4.进行黄金分割查找
    while ($left <= $right) {
        $mid = $left + $fibArr[$k - 1] - 1;//确定黄金分割位置,长度-1表示间隔距离
        if ($arr[$mid] == $val) {
            //判断是否是填充数据
            if ($mid > $right) {
                return $right;
            } else {
                return $mid;
            }
        } elseif ($arr[$mid] > $val) {
            //在左边
            $right = $mid - 1;
            $k -= 1;//左边区域长度F(k-1)
        } else {
            //在右边
            $left = $mid + 1;
            $k -= 2;//右边区域长度F(k-2)
        }
    }
    return -1;//没找到
}

记忆关键词: 斐波那契数列、黄金分割比例
性能分析:时间复杂度O(logn)

相关文章

  • JavaScript数据结构22—简单的查找算法

    以下算法包括了 顺序查找 插值查找 二分查找 斐波那契查找 输出 { index: 5, count: 10 }{...

  • 四大查找算法

    在Java中,常用的查找算法有以下四种: 顺序查找; 二分查找; 插值查找; 斐波那契查找; 欢迎大家关注我的公众...

  • 查找算法

    1、顺序查找 2、二分查找 3、插值查找 4、斐波那契查找 5、树表查找 6、分块查找 7、哈希查找 来自:Pol...

  • Java数据结构与算法:查找算法

    在java中,我们常用的查找有四种: 顺序(线性)查找 二分查找/折半查找 插值查找 斐波那契查找 1、线性查找 ...

  • 数据结构--查找

    查找分类 有序查找(二分查找、插值查找、斐波拉契查找) 线性索引查找 二叉排序树 散列表

  • day13

    查找算法 顺序查找 二分查找 差值查找 斐波那契查找 二分查找 前提数组必须是有序的。 升级 Interpolat...

  • 查找算法

    1. 顺序查找 2. 二分查找 3. 插值查找 4. 斐波那契查找 5. 树表查找 6. 分块查找 7. 哈希查找

  • 查找算法入门教程-黄金分割查找法(斐波拉契)

    前面我们学习了常见查找算法的插值和二分查找,这节我们来学习黄金分割查找法,也称斐波拉契,想必大家对斐波拉契函数f(...

  • 【查找算法】二分查找/插值查找/斐波那契查找(PHP)

    除了排序,查找指定值也是常见的功能,所以非常有必要掌握一下相关算法。经典查找算法有顺序查找、二分查找、差值查找、斐...

  • 查找算法-插值查找、斐波那契查找

    3.插值查找 插值查找其实是折半查找的升级版,在我们写折半查找的时候不知道大家想过没有 为什么每次要折一半呢?1/...

网友评论

    本文标题:【查找算法】二分查找/插值查找/斐波那契查找(PHP)

    本文链接:https://www.haomeiwen.com/subject/ytltkrtx.html