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版(5)
Oct 09 PHP
我的论坛源代码(一)
Oct 09 PHP
PHP 日期加减的类,很不错
Oct 10 PHP
解析php安全性问题中的:Null 字符问题
Jun 21 PHP
destoon实现会员商铺中指定会员或会员组投放广告的方法
Aug 21 PHP
php绘制一条弧线的方法
Jan 24 PHP
Laravel 5框架学习之表单
Apr 08 PHP
PHP安全下载文件的方法
Apr 07 PHP
YII2框架中使用yii.js实现的post请求
Apr 09 PHP
OAuth认证协议中的HMACSHA1加密算法(实例)
Oct 25 PHP
php插入mysql数据返回id的方法
May 31 PHP
ThinkPHP3.2.3框架实现执行原生SQL语句的方法示例
Apr 03 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微信开发之音乐回复功能
2018/06/14 PHP
基于jquery的loading 加载提示效果实现代码
2011/09/01 Javascript
jquery实现图片左右间隔滚动特效(可自动播放)
2013/05/08 Javascript
node.js中的events.emitter.once方法使用说明
2014/12/10 Javascript
js图片轮播特效代码分享
2015/09/07 Javascript
Ajax分页插件Pagination从前台jQuery到后端java总结
2016/07/22 Javascript
原生js实现轮播图的示例代码
2017/02/20 Javascript
详解Vue 非父子组件通信方法(非Vuex)
2017/05/24 Javascript
vue-router单页面路由
2017/06/17 Javascript
使用JavaScript实现链表的数据结构的代码
2017/08/02 Javascript
JavaScript实现body内任意节点的自定义属性功能示例
2017/09/18 Javascript
Vue组件的使用及个人理解与介绍
2019/02/09 Javascript
vue柱状进度条图像的完美实现方案
2019/08/26 Javascript
详解Node.JS模块 process
2020/08/31 Javascript
[07:40]DOTA2每周TOP10 精彩击杀集锦vol.4
2014/06/25 DOTA
Flask SQLAlchemy一对一,一对多的使用方法实践
2013/02/10 Python
python压缩文件夹内所有文件为zip文件的方法
2015/06/20 Python
python实现冒泡排序算法的两种方法
2018/03/10 Python
解决Matplotlib图表不能在Pycharm中显示的问题
2018/05/24 Python
python实现猜数字小游戏
2020/03/24 Python
python创建属于自己的单词词库 便于背单词
2019/07/30 Python
Python用access判断文件是否被占用的实例方法
2020/12/17 Python
介绍CSS3使用技巧5个
2009/04/02 HTML / CSS
HTML5 贪吃蛇游戏实现思路及源代码
2013/09/03 HTML / CSS
Alba Moda瑞士网上商店:独家意大利时尚女装销售
2016/11/28 全球购物
澳大利亚时尚前卫设计师珠宝在线:Amber Sceats
2017/10/04 全球购物
面向对象编程OOP的优点
2013/01/22 面试题
什么是servlet链?
2014/07/13 面试题
竞争上岗演讲稿
2014/01/05 职场文书
八一建军节部队活动方案
2014/02/04 职场文书
上班玩游戏检讨书
2014/02/07 职场文书
老公保证书范文
2014/04/29 职场文书
大学毕业生求职自荐书
2014/06/05 职场文书
建筑质检员岗位职责
2015/04/08 职场文书
餐厅开业活动方案
2019/07/08 职场文书
python 遍历磁盘目录的三种方法
2021/04/02 Python