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 相关文章推荐
php下使用curl模拟用户登陆的代码
Sep 10 PHP
php 计划任务 检测用户连接状态
Mar 29 PHP
php在线代理转向代码
May 05 PHP
zend Framework中的Layout(模块化得布局)详解
Jun 28 PHP
php根据身份证号码计算年龄的实例代码
Jan 18 PHP
php警告Creating default object from empty value 问题的解决方法
Apr 02 PHP
php使用GD2绘制几何图形示例
Feb 15 PHP
PHP 中使用explode()函数切割字符串为数组的示例
May 06 PHP
PHP基于堆栈实现的高级计算器功能示例
Sep 15 PHP
php+redis消息队列实现抢购功能
Feb 08 PHP
PDO::errorInfo讲解
Jan 28 PHP
TP5(thinkPHP5框架)基于bootstrap实现的单图上传插件用法示例
May 29 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中神奇的fastcgi_finish_request
2011/05/02 PHP
php生成excel列名超过26列大于Z时的解决方法
2014/12/29 PHP
php-fpm重启导致的程序执行中断问题详解
2019/04/29 PHP
基于jQuery的表格操作插件
2010/04/22 Javascript
js获得网页背景色和字体色的方法
2014/03/21 Javascript
jquery获取及设置outerhtml的方法
2015/03/09 Javascript
javascript入门教程基础篇
2015/11/16 Javascript
基于jquery实现简单的分页控件
2016/03/17 Javascript
详解JavaScript中双等号引起的隐性类型转换
2016/05/30 Javascript
JavaScript对象数组如何按指定属性和排序方向进行排序
2016/06/15 Javascript
jquery封装插件时匿名函数形参和实参的写法解释
2017/02/14 Javascript
jQuery实现文章图片弹出放大效果
2017/04/06 jQuery
JS中跳出循环的示例代码
2017/09/14 Javascript
用vue构建多页面应用的示例代码
2017/09/20 Javascript
vue打包后显示空白正确处理方法
2017/11/01 Javascript
element-ui 关于获取select 的label值方法
2018/08/24 Javascript
angular的输入和输出的使用方法
2018/09/22 Javascript
vue实现权限控制路由(vue-router 动态添加路由)
2019/11/04 Javascript
jQuery实现简单评论区功能
2020/10/26 jQuery
在Vue中使用mockjs代码实例
2020/11/25 Vue.js
[02:27]《DAC最前线》之附加赛征程
2015/01/29 DOTA
Python实现简单的四则运算计算器
2016/11/02 Python
python twilio模块实现发送手机短信功能
2019/08/02 Python
pytorch多进程加速及代码优化方法
2019/08/19 Python
python继承threading.Thread实现有返回值的子类实例
2020/05/02 Python
Django解决frame拒绝问题的方法
2020/12/18 Python
CSS3改变浏览器滚动条样式
2019/01/04 HTML / CSS
韩都衣舍天猫官方旗舰店:天猫女装销售总冠军
2017/10/10 全球购物
家庭户外服装:Hawkshead
2017/11/02 全球购物
Abbacino官网:包、钱包和女士配饰
2019/04/15 全球购物
应聘医药代表职位求职信
2013/10/21 职场文书
简单的项目建议书模板
2014/03/12 职场文书
党员教师工作决心书
2014/03/13 职场文书
四查四看整改措施
2014/09/19 职场文书
故宫英文导游词
2015/01/31 职场文书
PYTHON使用Matplotlib去实现各种条形图的绘制
2022/03/22 Python