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+MYSQL 出现乱码的解决方法
Aug 08 PHP
让php处理图片变得简单 基于gb库的图片处理类附实例代码下载
May 17 PHP
php使用curl检测网页是否被百度收录的示例分享
Jan 31 PHP
PHP数组排序之sort、asort与ksort用法实例
Sep 08 PHP
smarty中英文多编码字符截取乱码问题解决方法
Oct 28 PHP
smarty简单入门实例
Nov 28 PHP
php类的扩展和继承用法实例
Jun 20 PHP
php正则表达式学习笔记
Nov 13 PHP
PHP 的比较运算与逻辑运算详解
May 12 PHP
phalcon model在插入或更新时会自动验证非空字段的解决办法
Dec 29 PHP
基于PHP实现的多元线性回归模拟曲线算法
Jan 30 PHP
详解PHP PDO简单教程
May 28 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
VPS中使用LNMP安装WordPress教程
2014/12/28 PHP
codeigniter实现get分页的方法
2015/07/10 PHP
PHP加密解密实例分析
2015/12/25 PHP
PHP输出XML格式数据的方法总结
2017/02/08 PHP
PHP集成环境XAMPP的安装与配置
2018/11/13 PHP
javascript最常用与实用的创建类的代码
2010/08/12 Javascript
使用JavaScript检测Firefox浏览器是否启用了Firebug的代码
2010/12/28 Javascript
jQuery EasyUI API 中文文档 - DataGrid数据表格
2011/11/17 Javascript
jquery form 加载数据示例
2014/04/21 Javascript
教你如何使用node.js制作代理服务器
2014/11/26 Javascript
HTML5之WebSocket入门3 -通信模型socket.io
2015/08/21 Javascript
jquery实现向下滑出的二级导航下滑菜单效果
2015/08/25 Javascript
jQuery+CSS实现简单切换菜单示例
2016/07/27 Javascript
微信小程序Redux绑定实例详解
2017/06/07 Javascript
vue2.0 如何把子组件的数据传给父组件(推荐)
2018/01/15 Javascript
使用Vue制作图片轮播组件思路详解
2018/03/21 Javascript
JavaScript 正则命名分组【推荐】
2018/06/07 Javascript
支付宝小程序自定义弹窗dialog插件的实现代码
2018/11/30 Javascript
node.js实现为PDF添加水印的示例代码
2018/12/05 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
2019/05/07 Javascript
Vue+Element UI+vue-quill-editor富文本编辑器及插入图片自定义
2019/08/20 Javascript
[54:25]Ti4 循环赛第三日LGD vs MOUZ
2014/07/12 DOTA
使用python统计文件行数示例分享
2014/02/21 Python
Python中特殊函数集锦
2015/07/27 Python
python如何将两张图片生成为全景图片
2020/03/05 Python
《赠汪伦》教学反思
2014/04/12 职场文书
个人担保书范文
2014/05/20 职场文书
群众路线问题查摆对照检查材料
2014/10/04 职场文书
2014年党的群众路线活动个人整改措施
2014/10/28 职场文书
工作检讨书大全
2015/01/26 职场文书
学校推普周活动总结
2015/05/07 职场文书
数学复习课教学反思
2016/02/18 职场文书
golang 生成对应的数据表struct定义操作
2021/04/28 Golang
Python中X[:,0]和X[:,1]的用法
2021/05/10 Python
为什么MySQL8新特性会修改自增主键属性
2022/04/18 MySQL
Java设计模式中的命令模式
2022/04/28 Java/Android