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 相关文章推荐
56.com视频采集接口程序(PHP)
Sep 22 PHP
简单的php 验证图片生成函数
May 21 PHP
求PHP数组最大值,最小值的代码
Oct 31 PHP
PHP数据集构建JSON格式及新数组的方法
Nov 07 PHP
PHP彩蛋信息介绍和阻止泄漏的方法(隐藏功能)
Aug 06 PHP
PHP fastcgi模式上传大文件(大约有300多K)报错
Sep 28 PHP
浅谈ThinkPHP的URL重写
Nov 25 PHP
日常整理PHP中简单的图形处理(经典)
Oct 26 PHP
zend framework中使用memcache的方法
Mar 04 PHP
php 输入输出流详解及示例代码
Aug 25 PHP
PHP实现生成模糊图片的方法示例
Dec 21 PHP
laravel通用化的CURD的实现
Dec 13 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
咖啡知识大全
2021/03/03 新手入门
PHP默认安装产生系统漏洞
2006/10/09 PHP
在PHP中养成7个面向对象的好习惯
2010/01/28 PHP
php表单转换textarea换行符的方法
2010/09/10 PHP
php fsockopen解决办法 php实现多线程
2014/01/20 PHP
ThinkPHP3.1基础知识快速入门
2014/06/19 PHP
PHP实现对文件锁进行加锁、解锁操作的方法
2017/07/04 PHP
javascript Array.prototype.slice使用说明
2010/10/11 Javascript
jquery $.ajax各个事件执行顺序
2010/10/15 Javascript
扩展javascript的Date方法实现代码(prototype)
2010/11/20 Javascript
悄悄用脚本检查你访问过哪些网站的代码
2010/12/04 Javascript
jquery 获取表单元素里面的值示例代码
2013/07/28 Javascript
JavaScript版的TwoQueues缓存模型
2014/12/29 Javascript
JavaScript删除指定子元素代码实例
2015/01/13 Javascript
JavaScript数据结构与算法之链表
2016/01/29 Javascript
手机图片预览插件photoswipe.js使用总结
2016/08/25 Javascript
canvas雪花效果核心代码分享
2017/02/19 Javascript
微信小程序 商城开发(ecshop )简单实例
2017/04/07 Javascript
JavaScript原型继承_动力节点Java学院整理
2017/06/30 Javascript
Vue 过滤器filters及基本用法
2017/12/26 Javascript
详解小程序设置缓存并且不覆盖原有数据
2019/04/15 Javascript
使用Vue生成动态表单
2019/11/26 Javascript
[59:59]EG vs IG 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
使用python获取csv文本的某行或某列数据的实例
2018/04/03 Python
浅谈pycharm的xmx和xms设置方法
2018/12/03 Python
django 连接数据库 sqlite的例子
2019/08/14 Python
python的移位操作实现详解
2019/08/21 Python
Python守护进程实现过程详解
2020/02/10 Python
实例代码讲解Python 线程池
2020/08/24 Python
python 装饰器的使用示例
2020/10/10 Python
体育教师工作总结的自我评价
2013/10/10 职场文书
作风转变心得体会
2014/09/02 职场文书
我的职业生涯规划:打造自己的运动帝国
2014/09/18 职场文书
庆国庆国旗下讲话稿2014
2014/09/21 职场文书
2014年药剂科工作总结
2014/11/26 职场文书
关于观后感的作文
2015/06/18 职场文书