时间: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)