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 和 COM
Oct 09 PHP
在PHP中养成7个面向对象的好习惯
Jan 28 PHP
php 日期和时间的处理-郑阿奇(续)
Jul 04 PHP
让Nginx支持ThinkPHP的URL重写和PATHINFO的方法分享
Aug 08 PHP
PHP支持多种格式图片上传(支持jpg、png、gif)
Nov 03 PHP
php中通过数组进行高效随机抽取指定条记录的算法
Sep 09 PHP
php实现的CSS更新类实例
Sep 22 PHP
php发送html格式文本邮件的方法
Jun 10 PHP
Yii2基于Ajax自动获取表单数据的方法
Aug 10 PHP
php 计算两个时间相差的天数、小时数、分钟数、秒数详解及实例代码
Nov 09 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
Nov 14 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 中英文语言转换类代码
2011/08/11 PHP
ThinkPHP模板引擎之导入资源文件方法详解
2014/06/18 PHP
Redis在Laravel项目中的应用实例详解
2017/08/11 PHP
PHP addAttribute()函数讲解
2019/02/03 PHP
Yii框架的redis命令使用方法简单示例
2019/10/15 PHP
Juqery Html(),append()等方法的Bug解决方法
2010/12/13 Javascript
善用事件代理,警惕闭包的性能陷阱。
2011/01/20 Javascript
jQuery $.get 的妙用 访问本地文本文件
2012/07/12 Javascript
通过上下左右键和回车键切换光标实现代码
2013/03/08 Javascript
javascript:文字不间断向左移动的实例代码
2013/08/08 Javascript
纯js写的分页表格数据为json串
2014/02/18 Javascript
jquery制作弹窗提示窗口代码分享
2014/03/02 Javascript
Bootstrap打造一个左侧折叠菜单的系统模板(一)
2016/05/17 Javascript
JavaScript中误用/g导致的正则test()无法正确重复执行的解决方案
2016/07/27 Javascript
Bootstrap3 多选和单选框(checkbox)
2016/12/29 Javascript
微信小程序 input输入框详解及简单实例
2017/01/10 Javascript
jQuery按需加载轮播图(web前端性能优化)
2017/02/17 Javascript
JavaScript函数式编程(Functional Programming)纯函数用法分析
2019/05/22 Javascript
el-select 下拉框多选实现全选的实现
2019/08/02 Javascript
vue使用echarts实现水平柱形图实例
2020/09/09 Javascript
[01:28:43]2014 DOTA2华西杯精英邀请赛5 24 DK VS CIS
2014/05/25 DOTA
零基础写python爬虫之使用Scrapy框架编写爬虫
2014/11/07 Python
python循环监控远程端口的方法
2015/03/14 Python
python类继承用法实例分析
2015/05/27 Python
python+OpenCV实现车牌号码识别
2019/11/08 Python
PyTorch里面的torch.nn.Parameter()详解
2020/01/03 Python
python同时遍历两个list用法说明
2020/05/02 Python
Python3使用tesserocr识别字母数字验证码的实现
2021/01/29 Python
ziaja齐叶雅官方海外旗舰店:来自波兰的天然护肤品牌
2017/01/02 全球购物
美国孕妇装品牌:Destination Maternity
2018/02/04 全球购物
普通院校学生的自荐信
2013/11/27 职场文书
业务员的岗位职责
2014/03/15 职场文书
毕业生就业意向书
2014/04/01 职场文书
公务员试用期满考核材料
2014/05/22 职场文书
2016年春季运动会广播稿
2015/08/19 职场文书
《黄山奇石》教学反思
2016/02/18 职场文书