【捷哥浅谈PHP】第三弹—使用二分查找法查找数组中的元素位置

2013 年 1 月 31 日3640

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

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

那什么是二分法呢?

我来解释下:

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

也就是说,利用二分法查找的数据,必须是排好序的.

下面我们尝试查找数组array(1,2,3,4,5,6,7,8,9,10)中的某一个值的位置:

以上函数,第一个参数为传入的数组,第二个参数为该数组需要查询的值.

我们给数组的键设置一个最小值$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",查找成功,直接返回该值的索引即可.

也就是

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

    return $mid;

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

1,2,3,4,5,6,7,8,9,10

即为:

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

1,2,3,4,5,6,7,8,9,10

即为:

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

此函数的缺点在于:

如果数组中有重复的值,只能查到其中的一个值的键,有兴趣的童鞋,可以对以上函数进行完善,跟帖回复.

0 0