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通过COM使用ADODB的简单例子
Dec 31 PHP
PHP同时连接多个mysql数据库示例代码
Mar 17 PHP
php与Mysql的一些简单的操作
Feb 26 PHP
在php和MySql中计算时间差的方法详解
Mar 27 PHP
PHP学习笔记(二):变量详解
Apr 17 PHP
php去掉文件前几行的方法
Jul 29 PHP
php基础设计模式大全(注册树模式、工厂模式、单列模式)
Aug 31 PHP
php对二维数组进行相关操作(排序、转换、去空白等)
Nov 04 PHP
php pthreads多线程的安装与使用
Jan 19 PHP
php 截取中英文混合字符串的方法
May 31 PHP
浅析php如何实现爬取数据原理
Sep 27 PHP
php + ajax 实现的写入数据库操作简单示例
May 16 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 adodb分页实现代码
2009/03/19 PHP
在php和MySql中计算时间差的方法详解
2015/03/27 PHP
yii框架数据库关联查询操作示例
2019/10/14 PHP
Yii 框架使用数据库(databases)的方法示例
2020/05/19 PHP
jQuery 使用手册(七)
2009/09/23 Javascript
jquery select操作的日期联动实现代码
2009/12/06 Javascript
网页上的Javascript编辑器和代码格式化
2010/04/25 Javascript
浅析js封装和作用域
2013/07/09 Javascript
js 实现菜单上下显示附效果图
2013/11/21 Javascript
关于动态执行代码(js的Eval)实例详解
2016/08/15 Javascript
前端实现文件的断点续传(前端文件提交+后端PHP文件接收)
2016/11/04 Javascript
JS路由跳转的简单实现代码
2017/09/21 Javascript
JavaScript时间戳与时间日期间相互转换
2017/12/11 Javascript
AjaxUpLoad.js实现文件上传
2018/03/05 Javascript
JS中DOM元素的attribute与property属性示例详解
2018/09/04 Javascript
[00:08]DOTA2勇士令状等级奖励“天外飞星”
2019/05/24 DOTA
Python跳出循环语句continue与break的区别
2014/08/25 Python
Python实现网站文件的全备份和差异备份
2014/11/30 Python
利用python爬取斗鱼app中照片方法实例
2017/12/03 Python
Python3多线程爬虫实例讲解代码
2018/01/05 Python
Python读取stdin方法实例
2019/05/24 Python
python3文件复制、延迟文件复制任务的实现方法
2019/09/02 Python
基于python实现判断字符串是否数字算法
2020/07/10 Python
澳大利亚吉他在线:Artist Guitars
2017/03/30 全球购物
加拿大快时尚零售商:Ardene
2018/02/14 全球购物
俄罗斯购买自行车网站:Vamvelosiped
2021/01/29 全球购物
大学生关于奋斗的演讲稿
2014/01/09 职场文书
幼儿园课题实施方案
2014/05/14 职场文书
2014年作风建设工作总结
2014/10/29 职场文书
2014年银行柜员工作总结
2014/11/12 职场文书
试用期自我评价怎么写
2015/03/10 职场文书
食品卫生管理制度
2015/08/06 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
导游词之云南丽江-泸沽湖
2019/09/26 职场文书
祝福语集锦:给满月宝宝的祝福语
2019/11/20 职场文书
Pytest allure 命令行参数的使用
2021/04/18 Python