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 正确解码javascript中通过escape编码后的字符
Jan 28 PHP
php简单开启gzip压缩方法(zlib.output_compression)
Apr 13 PHP
php 表单提交大量数据发生丢失的解决方法
Mar 03 PHP
PHP常用的缓存技术汇总
May 05 PHP
PHP Streams(流)详细介绍及使用
May 12 PHP
php实现将上传word文件转为html的方法
Jun 03 PHP
php编写简单的文章发布程序
Jun 18 PHP
PHP代码判断设备是手机还是平板电脑(两种方法)
Oct 19 PHP
WordPress后台中实现图片上传功能的实例讲解
Jan 11 PHP
redis查看连接数及php模拟并发创建redis连接的方法
Dec 15 PHP
php 替换文章中的图片路径,下载图片到本地服务器的方法
Feb 06 PHP
PHP实现的curl批量请求操作示例
Jun 06 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中magic_quotes_gpc对unserialize的影响分析
2014/12/16 PHP
详解WordPress开发中用于获取分类及子页面的函数用法
2016/01/08 PHP
ThinkPHP框架搭建及常见问题(XAMPP安装失败、Apache/MySQL启动失败)
2016/04/15 PHP
PHP实现JS中escape与unescape的方法
2016/07/11 PHP
Yii2中使用asset压缩js,css文件的方法
2016/11/24 PHP
几个javascript操作word的参考代码
2009/10/26 Javascript
Extjs中TabPane如何嵌套在其他网页中实现思路及代码
2013/01/27 Javascript
jQuery动态设置form表单的enctype值(实现代码)
2013/07/04 Javascript
jQuery遍历Form示例代码
2013/09/03 Javascript
js/jquery获取文本框输入焦点的方法
2014/03/04 Javascript
jquery中ajax使用error调试错误的方法
2015/02/08 Javascript
angularJS结合canvas画图例子
2015/02/09 Javascript
jsonp跨域请求数据实现手机号码查询实例分析
2015/12/12 Javascript
JavaScript的Backbone.js框架环境搭建及Hellow world示例
2016/05/07 Javascript
微信小程序 视图层(xx.xml)和逻辑层(xx.js)详细介绍
2016/10/13 Javascript
简单理解js的prototype属性及使用
2016/12/07 Javascript
深入nodejs中流(stream)的理解
2017/03/27 NodeJs
JS/jquery实现一个网页内同时调用多个倒计时的方法
2017/04/27 jQuery
ES6使用export和import实现模块化的方法
2018/09/10 Javascript
使用Python实现下载网易云音乐的高清MV
2015/03/16 Python
用Python的Flask框架结合MySQL写一个内存监控程序
2015/11/07 Python
如何处理Python3.4 使用pymssql 乱码问题
2016/01/08 Python
总结python爬虫抓站的实用技巧
2016/08/09 Python
Python之用户输入的实例
2018/06/22 Python
python实现在图片上画特定大小角度矩形框
2018/10/24 Python
Python imageio读取视频并进行编解码详解
2019/12/10 Python
实习生自荐信范文
2013/11/13 职场文书
《石榴》教学反思
2014/03/02 职场文书
双语教学实施方案
2014/03/23 职场文书
安全责任协议书
2014/04/21 职场文书
领导干部群众路线教育实践活动剖析材料
2014/10/10 职场文书
迁户口计划生育证明
2014/10/19 职场文书
学校机关党总支领导班子整改工作方案
2014/10/26 职场文书
学习焦裕禄观后感
2015/06/09 职场文书
驾驶员管理制度范本
2015/08/06 职场文书
共青团优秀团员申请书(范文)
2019/08/15 职场文书