二分查找原理与分析

时间:2014.04.01

地点:基地二楼

------------------------------------------------------------------------------------

一、概述

  嗯,二叉查找的思想还是很简单的,在有序数组的查找中非常有用,比如在按字母排序的字符串中查找,对按序排列的号码查找。我们在设计这个二叉查找的函数时可指明:

1.数组本身 2.查找起始下标 3.查找元素的个数 4.查找目标 5.查找情况 6.位置。函数原型如下:

viod search(const int a[],size_t first,sizet_t size,int target,bool& found, size_t& location
//前置条件:数组a从小到大排序

//后置条件:从a[first]开始,含size个元素的数组段内查找给定元素target,找到found为true,并设置location,否则found设置为false

-----------------------------------------------------------------------------------

二、设计

递归实现,算法的伪代码如下:

if(size==0)
  found=false;
else{
  middle=数组段近似中点的下标;
  if(target==a[middle])
    目标在a[middle]处找到
  else if(target<a[middle])
    在中间点的前面部分查找目标
  else if(target>a[middle])
    在中间点的后面部分查找目标
}


在算法的递归实现中,我们必须保证函数的递归能够正确地终止,因此每次递归调用都会查找一个更小的列表,当列表长度为0时不再继续递归调用。在这里size是一个有效的变量表达式,阈值为0,即size没调用一次,都至少会减少1,size为0时不再继续调用。

-----------------------------------------------------------------------------------

三、函数的实现

viod search(const int a[],size_t first,size_t size,int target,bool& found,size_t& location)
//Precondition: ......
//Postcondition: ......
//Library facilities used: 
{
  size_t middle;
  if(size==0)
    found=false;
  else{
    middle=first+size/2;
    if(target==a[middle){
        loacatin=middle;    
        found=true;
    }
    else if(target<a[middle])
        search(a,first,size/2,target,found,loacation);
    else
        search(a,middle+1,(size-1)/2,target,found,location);
  }
}

这里有几个经验总结和常见错误

1.已知数组起始索引first和元素个数size,求近似中间元素索引公式为:

middle=first+size/2

2.已知数组元素个数为size,那么以中间元素为分界,两边都不包活中间元素,则左边段含有size/2个元素,右边段含有 (size-1)/2个元素

3.数组连续索引区间上[a,b)共含有 b-a 个元素

4.你应该尽量避免为负的size_t值,以免程序在运行时发生错误。

-----------------------------------------------------------------------------------

四、分析

  二叉查找最坏的情况就是查找目标不在数组中,如此会一次又一次的递归下去,直到size一半一半的减少到0,没迭代一次,size都会在原来的基础上缩小一半,

这里有个概念叫做递归调用深度:即最长递归调用链的长度。在n个元素的数组中进行二叉查找的递归调用深度最多为n被2除的次数,当结果小于1时停止。

所以二叉查找的最坏运行时间T(n)=(每次最坏迭代运算次数)*(最长递归调用链长度)+停止情况时执行的运算次数

                                                           =18*(最长递归调用长度)+2

                                                           =18*(n可以被2除的次数,当结果小于1时停止)+2

                                                           =18*H(n)+2

H(n)为二分函数,可以看出H(n)约等于以2为底的n的对数,即log2(n),更准确地说二分函数的值H(n)=floor(  log2(n)  )+1
,在分析算法效率时我们常丢掉常数部分,认为该算法的最坏情况运行时间是对数级别的,即O(log n)。

总结:对于有n个元素的数组来说,二叉查找的算法最坏运行时间是对数级的,为O(log n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值