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
PHP4和PHP5性能测试和对比 测试代码与环境
Aug 17 PHP
Zend Studio for Eclipse的java.lang.NullPointerException错误的解决方法
Dec 06 PHP
PHP setcookie() cannot modify header information 的解决方法
Jan 09 PHP
php面向对象全攻略 (二) 实例化对象 使用对象成员
Sep 30 PHP
php设计模式 Factory(工厂模式)
Jun 26 PHP
php中通过正则表达式下载内容中的远程图片的函数代码
Jan 10 PHP
Mysql中分页查询的两个解决方法比较
May 02 PHP
一个漂亮的php验证码类(分享)
Aug 06 PHP
PHP实现的浏览器检查类
Apr 11 PHP
PHP基于PDO实现的SQLite操作类【包含增删改查及事务等操作】
Jun 21 PHP
php面向对象重点知识分享
Sep 27 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初学者最感迷茫的问题小结
2010/03/27 PHP
PHP中用hash实现的数组
2011/07/17 PHP
PHP针对字符串开头和结尾的判断方法
2016/07/11 PHP
PHP封装的分页类与简单用法示例
2019/02/25 PHP
PHP使用PDO实现mysql防注入功能详解
2019/12/20 PHP
CL vs ForZe BO5 第二场 2.13
2021/03/10 DOTA
JavaScript窗口功能指南之在窗口中书写内容
2006/07/21 Javascript
jquery下动态显示jqGrid以及jqGrid的属性设置容易出现问题的解决方法
2010/10/22 Javascript
js分解url参数(面向对象-极简主义法应用)
2012/08/09 Javascript
jQuery中:first选择器用法实例
2014/12/30 Javascript
JavaScript实现动态删除列表框值的方法
2015/08/12 Javascript
jQuery实现带幻灯的tab滑动切换风格菜单代码
2015/08/27 Javascript
jquery注册文本框获取焦点清空,失去焦点赋值的简单实例
2016/09/08 Javascript
jQ处理xml文件和xml字符串的方法(详解)
2016/11/22 Javascript
微信小程序 less文件编译成wxss文件实现办法
2016/12/05 Javascript
node.js+jQuery实现用户登录注册AJAX交互
2017/04/28 jQuery
vue一步步实现alert功能
2017/07/05 Javascript
vue项目如何刷新当前页面的方法
2018/05/18 Javascript
vue.js中ref和$refs的使用及示例讲解
2019/08/14 Javascript
Python Requests 基础入门
2016/04/07 Python
python 调用c语言函数的方法
2017/09/29 Python
Python扩展内置类型详解
2018/03/26 Python
Python根据欧拉角求旋转矩阵的实例
2019/01/28 Python
python已协程方式处理任务实现过程
2019/12/27 Python
你应该知道的Python3.6、3.7、3.8新特性小结
2020/05/12 Python
python爬虫实例之获取动漫截图
2020/05/31 Python
python制作一个简单的gui 数据库查询界面
2020/11/19 Python
详解HTML5将footer置于页面最底部的方法(CSS+JS)
2018/10/11 HTML / CSS
世界上最大的在线旅行社新加坡网站:Expedia新加坡
2016/08/25 全球购物
企划主管岗位职责
2013/12/12 职场文书
《闻一多先生的说和做》教学反思
2014/04/28 职场文书
个人师德师风自我剖析材料
2014/09/29 职场文书
2014年英语教学工作总结
2014/12/17 职场文书
关爱留守儿童捐款倡议书
2015/04/27 职场文书
SQL Server基本使用和简单的CRUD操作
2021/04/05 SQL Server
CSS的calc函数用法小结
2022/06/25 HTML / CSS