折半查找的算法思想
折半查找,又称"二分查找",仅适用于有序的顺序表
查找成功的例子:
因为33大于mid,所有只可能在右边区域
因为33小于mid,所有只可能在左边区域
mid=(32+33)/2=32<33,所有只可能在右边区域
查找成功!
查找失败的例子
12<mid,只可能在左边
12<mid,只可能在左边
12>mid,只可能在右边
12>mid,只可能在右边,因为是最后一个元素,将low=mid+1
折半查找的实现
typedef struct {//查找表的数据结构(顺序表)
ElemType* elem;//动态数组地址
int TableLen;//表的长度
}SSTable;
//折半查找
int Binary_Search(SSTable L, ElemType key) {
int low = 0, high = L.TableLen - 1, mid;
while (low<=high)
{
mid=(low + high) / 2;//取中间位置
if (L.elem[mid] == key)
return mid;//查找成功则返回所在位置
else if (L.elem[mid] > key)
high = mid - 1;//从前半部分进行查找
else
low = mid + 1;//从后半部分进行查找
}
return -1;//查找失败,返回-1
}
查找效率分析
将所有mid结点寻找出来,制成一个查找判定树
折半查找判定树的构造
结点数为奇数情况
如果当前low和high之间有奇数个元素,则mid分隔后,左右两部分元素个数相等
结点数为偶数情况
如果当前low和high之间有偶数个元素,则mid分隔后,左半部分比右半部分少一个元素
结论:
折半查找的判定树中,若mid=[(low+high)/2],则对于任何一个结点,必有:
右子树结点树-左子树结点树=0或1
mid向下取整:右子树比左子树多一个或零个孩子
mid向上取整:左子树比右子树多一个或零个孩子
练习:
答案:
注意:折半查找的判定树一定是平衡二叉树
折半查找的判定树中,只有最下面一层是不满的,因此,元素个为n时树高h=[]
判定树结点关键字:左<中<右,满足二叉排序树的定义
失败结点:n+1个(等于成功结点的空链域数量)
折半查找的查找效率
树高h=[](不包含失败结点)
查找成功的ASL<=h
查找成功的ASL<=h
折半查找的时间复杂度 =
扩展
折半查找不一定比顺序查找快
若mid向上取整
mid向上取整:左子树比右子树多一个或零个孩子