当前位置:首页 > PHP > 使用二分法查找数组中的元素位置

使用二分法查找数组中的元素位置

在php中我们可以通过array_search()函数来查找一个数组内的元素值的键名.

同样,我们可以通过使用二分法来查找数组内的元素的键名.
那什么是二分法呢?

我来解释下:
如果数据是按升序排序的,我们从数据的中间位置开始查找,若给定的值恰好等于当前位置的值,查找成功,若给定的值小于当前位置的值,那我们就从以当前值为准查找其前半部分的值,反之,若给定的值大于当前值,那么就从以当前值为准查找其后半部分的值.

也就是说,利用二分法查找的数据,必须是排好序的.
下面我们尝试查找数组array(1,2,3,4,5,6,7,8,9,10)中的某一个值的位置:

复制代码

1.    <?php

2.    function Search($a,$val){

3.            $low = 0;

4.            $high= count($a)- 1;

5.            while($low <=$high){

6.                $mid= intval(($low+$high)/2);

7.                if($a[$mid]== $val)

8.                    return$mid;

9.                if($a[$mid]> $val){

10.                  $high= $mid – 1;

11.              }else{

12.                  $low= $mid + 1;

13.              }

14.          }

15.          return -1;

16.      }

17.  ?>
以上函数,第一个参数为传入的数组,第二个参数为该数组需要查询的值.
我们给数组的键设置一个最小值$low为0,设置一个最大值为$high为数组长度减一,那么中间值我们就可以设置为intval(($low+$height)/2),
也就是说,当数组元素长度为奇数时,数组的中间值正好在正中间,
例如数组长度为5,那中间值正好为2,也就是(0+4)/2,
0,1,2,3,4
那当我们的数组长度为偶数时,利用上述公式是无法除尽的,所以我们要取整,无论是进一法取整还是舍去法取整都是可以的
例如数组长度为6,那中间值为(0+5)/2,值为2.5,那数组中键为2.5的是不存在的,所以我们就需要取整为2
0,1,2,3,4,5
如果使用上述取整函数intval或者是floor函数获得的键为2,如果使用ceil取整,这里得到的键即为3

那么,我们拿上面的数组来说:
数组的长度为10,那么中间值即为intval((0+(10-1))/2),为4,索引为4的也就是数组中的第五个元素”5″
1,2,3,4,5,6,7,8,9,10

好,我们下面开始判断,
1.如果需要查询的值恰好为”5″,查找成功,直接返回该值的索引即可.
也就是

复制代码

1.    if($a[$mid] == $val)

2.    return $mid;

2.如果要查询的值小于”5″,我们需要把$high的值设为中间值减一,即为4-1,并返回继续查询中间值的前半部分(红色部分)
1,2,3,4,5,6,7,8,9,10
即为:

复制代码

1.    if($a[$mid] > $val){

2.    $high = $mid - 1;

3.    }

3.如果要查询的值大于”5″,我们就需要把$low的值设为中间值加一,即为4+1,并返回继续查询中间值的后半部分(红色部分)
1,2,3,4,5,6,7,8,9,10
即为:

复制代码

1.    else{

2.    $low = $mid + 1;

3.    }

设置完之后,返回继续查询,如果满足条件$low<=$high,就反复查询,直到此条件不成立,也就是被查询的范围小于一个数组元素时,说要查询的值在数组中不存在,返回-1.

复制代码

1.    while($low <= $high){

2.    …….

3.    }

4.    return -1;

此函数的缺点在于:
如果数组中有重复的值,只能查到其中的一个值的键,有兴趣的童鞋,可以对以上函数进行完善

 

本文来自 OpenFree   www.it163.org

  • «
  • »
  • 作者:
    除非注明,本文原创:OpenFree,专注于IT互联网,欢迎转载!转载请以链接形式注明本文地址,谢谢。
    原文链接:http://www.it163.org/post/118fd1_76cc13

    发表评论

    电子邮件地址不会被公开。 必填项已用*标注


    您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>