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 缓冲的免费实现方法
Oct 09 PHP
php的计数器程序
Oct 09 PHP
一个高ai的分页函数和一个url函数
Oct 09 PHP
windows xp下安装pear
Dec 02 PHP
PHP写入WRITE编码为UTF8的文件的实现代码
Jul 07 PHP
PHP Stream_*系列函数
Aug 01 PHP
Ubuntu中启用php的mail()函数并解决发送邮件速度慢问题
Mar 27 PHP
php 把数字转换成汉字的代码
Jul 21 PHP
PHP实现抓取迅雷VIP账号的方法
Jul 30 PHP
WordPress中用于获取搜索表单的PHP函数使用解析
Jan 05 PHP
php用户登录之cookie信息安全分析
May 13 PHP
老生常谈PHP面向对象之注册表模式
May 26 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
PHP5中MVC结构学习
2006/10/09 PHP
php桌面中心(二) 数据库写入
2007/03/11 PHP
php UTF8 文件的签名问题
2009/10/30 PHP
memcached 和 mysql 主从环境下php开发代码详解
2010/05/16 PHP
linux下为php添加curl扩展的方法
2011/07/29 PHP
table标签的结构与合并单元格的实现方法
2013/07/24 PHP
php命名空间学习详解
2014/02/27 PHP
PHP中FTP相关函数小结
2016/07/15 PHP
如何让PHP编码更加好看利于阅读
2019/05/12 PHP
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
使用户点击后退按钮使效三行代码
2007/07/07 Javascript
jQuery多项选项卡的实现思路附样式及代码
2014/06/03 Javascript
javascript创建对象、对象继承的实用方式详解
2016/03/08 Javascript
javascript jquery对form元素的常见操作详解
2016/06/12 Javascript
Bootstrap模态框水平垂直居中与增加拖拽功能
2016/11/09 Javascript
Angular的$http与$location
2016/12/26 Javascript
mint-ui的search组件在键盘显示搜索按钮的实现方法
2017/10/27 Javascript
JS实现的RC4加密算法示例
2018/08/16 Javascript
基于Nodejs的Tcp封包和解包的理解
2018/09/19 NodeJs
详解使用mocha对webpack打包的项目进行&quot;冒烟测试&quot;的大致流程
2020/04/27 Javascript
浅析JavaScript 函数柯里化
2020/09/08 Javascript
[01:06:43]完美世界DOTA2联赛PWL S3 PXG vs GXR 第二场 12.19
2020/12/24 DOTA
tensorflow输出权重值和偏差的方法
2018/02/10 Python
python实现彩票系统
2020/06/28 Python
Python和Go语言的区别总结
2019/02/20 Python
python使用matplotlib画柱状图、散点图
2019/03/18 Python
500行Python代码打造刷脸考勤系统
2019/06/03 Python
pytorch 预训练层的使用方法
2019/08/20 Python
Python中文分词库jieba,pkusegwg性能准确度比较
2020/02/11 Python
keras model.fit 解决validation_spilt=num 的问题
2020/06/19 Python
.NET面试问题集
2015/12/08 面试题
在C#中如何实现多态
2014/07/02 面试题
实习单位推荐信范文
2013/11/27 职场文书
乡镇团代会开幕词
2016/03/04 职场文书
python 中yaml文件用法大全
2021/07/04 Python
使用CSS实现一个搜索引擎的原理解析
2021/09/25 HTML / CSS