PHP有序表查找之插值查找算法示例


Posted in PHP onFebruary 10, 2018

本文实例讲述了PHP有序表查找之插值查找算法。分享给大家供大家参考,具体如下:

前言:

在前面我们介绍了二分查找,但是我们考虑一下,为什么一定要折半呢?而不是折四分之一或者更多?

打个比方,在英文词典里查找“apple”,你下意识里翻开词典是翻前面的书页还是后面的书页呢?如果再查“zoo”,你又会怎么查?显然你不会从词典中间开始查起,而是有一定目的地往前或往后翻。

同样,比如要在取值范围在 0 ~ 10000 之间的100个元素从小到大均匀分布的数组中查找5,我们自然而然地先考虑数组下标较小的开始查找。

以上的分析其实就是插值查找的思想,它是二分查找的改进。

基本思想:

根据要查找的关键字key与查找表中的最大最小记录的关键字比较后的查找方法,其核心就在于插值计算公式,我们先看折半查找的计算公式:

 PHP有序表查找之插值查找算法示例

而插值查找就是要将其中的 1/2进行改进,改成下面的计算方案:

 PHP有序表查找之插值查找算法示例

插值查找算法的核心就在于插值的计算公式:

$num - $arr[$lower]
—————————————
$arr[$high] - $arr[$lower]

代码:

<?php
//插值查找(前提是数组必须是有序数组) 事件复杂度 O(logn)
//但对于数组长度比较大,关键字分布又是比较均匀的来说,插值查找的效率比折半查找的效率高
$i = 0; //存储对比的次数
//@param 待查找数组
//@param 待搜索的数字
function insertsearch($arr,$num){
 $count = count($arr);
 $lower = 0;
 $high = $count - 1;
 global $i;
 while($lower <= $high){
  $i ++; //计数器
  if($arr[$lower] == $num){
   return $lower;
  }
  if($arr[$high] == $num){
   return $high;
  }
  // 折半查找 : $middle = intval(($lower + $high) / 2);
  $middle = intval($lower + ($num - $arr[$lower]) / ($arr[$high] - $arr[$lower]) * ($high - $lower)); 
  if($num < $arr[$middle]){
   $high = $middle - 1;
  }else if($num > $arr[$middle]){
   $lower = $middle + 1;
  }else{
   return $middle;
  }
 }
 return -1;
}
$arr = array(0,1,16,24,35,47,59,62,73,88,99);
$pos = insertsearch($arr,62);
print($pos);
echo "<br>";
echo $i;

总结:

从时间复杂度上来看,它也是 O(logn),但对于有序表比较长,而关键字分布有比较均匀的查找表来说,插值查找算法的平均性能比二分查找好的多。反之,数组中如果分布类似于{0,1,2,2000,2001,。。。999998,999999}这种极端不均匀的数据,用插值查找未必是很合适的选择。

我自己特别做了个例子:

$arr = array(0,1,2,2000,2001,2002,2003,2004,5555,69666,99999,100000);
echo "位置:".binsearch($arr,5555);
echo "<br>";
echo "比较次数:".$i;
$i = 0; //重置比较次数
echo "<br>";
echo "位置:".insertsearch($arr,5555);
echo "<br>";
echo "比较次数:".$i;

结果输出:

位置:8
比较次数:2
位置:8
比较次数:9

可以得到,对于极端不均匀的数据,插值查找效率比折半查找低。

PS:上面提到的binsearch()函数大家可以参考前面一篇 PHP有序表查找—-二分查找(折半)

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
用文本作数据处理
Oct 09 PHP
域名查询代码公布
Oct 09 PHP
将一维或多维的数组连接成一个字符串的php代码
Aug 08 PHP
PHP设计模式 注册表模式
Feb 05 PHP
ThinkPHP3.0略缩图不能保存到子目录的解决方法
Sep 30 PHP
php中如何使对象可以像数组一样进行foreach循环
Aug 09 PHP
php文件上传的两种实现方法
Apr 04 PHP
[原创]php简单隔行变色功能实现代码
Jul 09 PHP
Smarty3配置及入门语法
Feb 22 PHP
php实现不通过扩展名准确判断文件类型的方法【finfo_file方法与二进制流】
Apr 18 PHP
PHP基于关联数组20行代码搞定约瑟夫问题示例
Nov 07 PHP
Laravel如何使用Redis共享Session
Feb 23 PHP
PHP有序表查找之二分查找(折半查找)算法示例
Feb 09 #PHP
php在windows环境下获得cpu内存实时使用率(推荐)
Feb 08 #PHP
PHP基于redis计数器类定义与用法示例
Feb 08 #PHP
php处理抢购类功能的高并发请求
Feb 08 #PHP
php+redis实现商城秒杀功能
Nov 19 #PHP
php+redis消息队列实现抢购功能
Feb 08 #PHP
PHP多线程模拟实现秒杀抢单
Feb 07 #PHP
You might like
php带密码功能并下载远程文件保存本地指定目录 修改加强版
2010/05/16 PHP
PHP中的排序函数sort、asort、rsort、krsort、ksort区别分析
2014/08/18 PHP
PHP遍历文件夹与文件类及处理类用法实例
2014/09/23 PHP
简单解决新浪SAE无法上传文件的问题
2015/05/13 PHP
JQuery 写的个性导航菜单
2009/12/24 Javascript
js防止表单重复提交实现代码
2012/09/05 Javascript
深入浅析JavaScript的API设计原则
2016/06/14 Javascript
详解Angular4中路由Router类的跳转navigate
2017/06/09 Javascript
详谈ES6中的迭代器(Iterator)和生成器(Generator)
2017/07/31 Javascript
Vue中的作用域CSS和CSS模块的区别
2018/10/09 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
2019/05/07 Javascript
npm的lock机制解析
2019/06/20 Javascript
uni-app微信小程序登录并使用vuex存储登录状态的思路详解
2019/11/04 Javascript
vue-cli3配置favicon.ico和title的流程
2020/10/27 Javascript
JS实现选项卡插件的两种写法(jQuery和class)
2020/12/30 jQuery
[01:20]DOTA2上海特级锦标赛现场采访:谁的ID最受青睐
2016/03/25 DOTA
Python正则简单实例分析
2017/03/21 Python
如何基于python操作json文件获取内容
2019/12/24 Python
Django实现将views.py中的数据传递到前端html页面,并展示
2020/03/16 Python
python实现3D地图可视化
2020/03/25 Python
Python3标准库之threading进程中管理并发操作方法
2020/03/30 Python
解决使用python print打印函数返回值多一个None的问题
2020/04/09 Python
Python如何在单元测试中给对象打补丁
2020/08/03 Python
详解numpy.ndarray.reshape()函数的参数问题
2020/10/13 Python
英语简历自我评价
2014/01/26 职场文书
体育课课后反思
2014/04/24 职场文书
班主任与学生安全责任书
2014/07/25 职场文书
学党史心得体会
2014/09/05 职场文书
运动会400米加油稿(8篇)
2014/09/22 职场文书
离婚协议书应该怎么写
2014/10/12 职场文书
军人离婚协议书样本
2014/10/21 职场文书
病危通知书样本
2015/04/17 职场文书
2015学校六五普法工作总结
2015/04/22 职场文书
python 中yaml文件用法大全
2021/07/04 Python
PostgreSQL常用字符串分割函数整理汇总
2022/07/07 PostgreSQL
mysql函数之截取字符串的实现
2022/08/14 MySQL