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 相关文章推荐
dedecms系统的广告设置代码 基础版本
Apr 09 PHP
PHP PDO函数库详解
Apr 27 PHP
队列在编程中的实际应用(php)
Sep 04 PHP
PHP中使用memcache存储session的三种配置方法
Apr 05 PHP
php简单分页类实现方法
Feb 26 PHP
Symfony控制层深入详解
Mar 17 PHP
PHP session会话操作技巧小结
Sep 27 PHP
php中通过eval实现字符串格式的计算公式
Mar 18 PHP
PHP递归删除多维数组中的某个值
Apr 17 PHP
PHP框架Laravel中实现supervisor执行异步进程的方法
Jun 07 PHP
php apache开启跨域模式过程详解
Jul 08 PHP
PHP正则之正向预查与反向预查讲解与实例
Apr 06 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&amp;mysql(三)
2006/10/09 PHP
PHP使用DirectoryIterator显示下拉文件列表的方法
2015/03/13 PHP
一个js实现的所谓的滑动门
2007/05/23 Javascript
JavaScript 应用类库代码
2008/06/02 Javascript
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
2009/11/28 Javascript
Firefox中beforeunload事件的实现缺陷浅析
2012/05/03 Javascript
JS对话框_JS模态对话框showModalDialog用法总结
2014/01/11 Javascript
jquery绑定事件不生效的解决方法
2014/02/11 Javascript
jQuery实现按钮只点击一次后就取消点击事件绑定的方法
2015/06/26 Javascript
vue-dialog的弹出层组件
2020/05/25 Javascript
通过js修改input、select默认字体颜色
2017/04/19 Javascript
bootstrap表单示例代码分享
2017/05/18 Javascript
深入浅析JavaScript中的RegExp对象
2017/09/18 Javascript
详解通过源码解析Node.js中cluster模块的主要功能实现
2018/05/16 Javascript
深入理解Vue router的部分高级用法
2018/08/15 Javascript
JS实现的input选择图片本地预览功能示例
2018/08/29 Javascript
JS与jQuery判断文本框还剩多少字符可以输入的方法
2018/09/01 jQuery
selenium+java中用js来完成日期的修改
2019/10/31 Javascript
使用vue-cli4.0快速搭建一个项目的方法步骤
2019/12/04 Javascript
浅析JS中NEW的实现原理及重写
2020/02/20 Javascript
详解Python的Django框架中Manager方法的使用
2015/07/21 Python
python 捕获shell脚本的输出结果实例
2017/01/04 Python
Python实现的选择排序算法示例
2017/11/29 Python
Python PIL图片添加字体的例子
2019/08/22 Python
详解Python IO编程
2020/07/24 Python
用 python 进行微信好友信息分析
2020/11/28 Python
详解修改Anaconda中的Jupyter Notebook默认工作路径的三种方式
2021/01/24 Python
浅谈html5增强的页面元素
2016/06/14 HTML / CSS
兰蔻加拿大官方网站:Lancome加拿大
2016/08/05 全球购物
全球最大的房车租赁市场:Outdoorsy
2018/09/19 全球购物
EJB2和EJB3在架构上的不同点
2014/09/29 面试题
自荐书范文
2013/12/08 职场文书
桥梁工程专业求职信
2014/04/21 职场文书
卫生院健康教育实施方案
2014/06/07 职场文书
学校周年庆活动方案
2014/08/22 职场文书
小学班主任事迹材料
2014/12/17 职场文书