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中利用wsdl创建标准webservice的实现代码
Dec 07 PHP
PHP imagecreatefrombmp 从BMP文件或URL新建一图像
Jul 16 PHP
php 模拟POST提交的2种方法详解
Jun 17 PHP
php实现查询百度google收录情况(示例代码)
Aug 02 PHP
PHP Reflection API详解
May 12 PHP
谈谈你对Zend SAPIs(Zend SAPI Internals)的理解
Nov 10 PHP
WordPress中查询文章的循环Loop结构及用法分析
Dec 17 PHP
PHP实现的线索二叉树及二叉树遍历方法详解
Apr 25 PHP
php实现微信扫码自动登陆与注册功能
Sep 22 PHP
Yii实现文章列表置顶功能示例
Oct 18 PHP
浅谈PHP中pack、unpack的详细用法
Mar 12 PHP
PDO实现学生管理系统
Mar 21 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
第十节--抽象方法和抽象类
2006/11/16 PHP
php和javascript之间变量的传递实现代码
2012/12/19 PHP
解决php使用异步调用获取数据时出现(错误c00ce56e导致此项操作无法完成)
2013/07/03 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
2015/08/31 PHP
PHP书写格式详解(必看)
2016/05/23 PHP
PHP实现登录验证码校验功能
2018/05/17 PHP
PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析
2019/06/12 PHP
checkbox 复选框不能为空
2009/07/11 Javascript
window.onbeforeunload方法在IE下无法正常工作的解决办法
2010/01/23 Javascript
javascript中万恶的function实例分析
2011/05/25 Javascript
广泛收集的jQuery拖放插件集合
2012/04/09 Javascript
jQuery写fadeTo示例代码
2014/02/21 Javascript
你未必知道的JavaScript和CSS交互的5种方法
2014/04/02 Javascript
简述JavaScript的正则表达式中test()方法的使用
2015/06/16 Javascript
JS实现横向与竖向两个选项卡Tab联动的方法
2015/09/27 Javascript
Vue-cli创建项目从单页面到多页面的方法
2017/09/20 Javascript
原生JS实现手动轮播图效果实例代码
2018/11/22 Javascript
vue+Element实现搜索关键字高亮功能
2019/05/28 Javascript
Vue项目中ESlint规范示例代码
2019/07/04 Javascript
vuex刷新后数据丢失的解决方法
2020/10/18 Javascript
[01:33:59]真人秀《加油 DOTA》 第六期
2014/09/09 DOTA
Python的Flask框架中实现简单的登录功能的教程
2015/04/20 Python
python中实现迭代器(iterator)的方法示例
2017/01/19 Python
Python之re操作方法(详解)
2017/06/14 Python
Jupyter Notebook远程登录及密码设置操作
2020/04/10 Python
HTML5使用ApplicationCache接口实现离线缓存技术解决离线难题
2012/12/13 HTML / CSS
葡萄牙鞋子品牌:Fair
2016/12/10 全球购物
尼克松手表官网:Nixon手表
2019/03/17 全球购物
加大码胸罩、内裤和服装:Just My Size
2019/03/21 全球购物
介绍一下Python下range()函数的用法
2013/11/07 面试题
影视艺术学院毕业生自荐信
2013/11/13 职场文书
医学生职业规划范文
2014/01/05 职场文书
职业生涯规划书结束语
2014/04/15 职场文书
大学生考试作弊检讨书1000字
2014/10/14 职场文书
自愿离婚协议书范本2016
2016/03/18 职场文书
详解MySQL集群搭建
2021/05/26 MySQL