#引言
在做折半插入排序时,发现自己对于二分的理解不是很充分,特别是二分查找失败时左右指针的位置。
本来想着单纯推导一下,但发现推导一遍后不仅知道了这个问题的答案,对于二分查找也有了更深的理解。
#结论
若用left、right和mid分别记录二分查找时的左标记指针、右标记指针和中间位置标记指针。
对元素在查找序列
进行查找,则在查找结束时,无论查找是否成功,查找序列中left所指向元素的左边的元素都比
小,right所指向元素的右边的元素都比
大。
#举例分析
查找序列为(7,10,13,16,19),画出折半查找的判定树如下:

树的所有叶子结点都意味着查找失败,n个元素的序列划分出了n+1个取值范围。
判定树其实是画出了mid这个索引标记的走向,即从13这个元素(初始时序列最中间)开始,最后走到叶子(取值范围)结点意味着查找失败,非叶子结点意味着查找成功。
在这颗判定树上,left和right在查找过程中的变化并不好观察,但我们知道查找失败时,查找值在某个叶子结点表示的范围内,也就是查找失败时的前一步,left、right和mid都指向该叶子结点的父结点。
比如查找值为12,我们一定会走到下图的地步:

此时left,right,mid都指向元素10。
下一步判定12>10,则left=left+1,right不变,导致left>right,打破二分查找的循环条件,查找失败。

显然
right指向的是序列(7,10,13,16,19)中比12小,且离得最近的元素10
left指向的是序列(7,10,13,16,19)中比12大,且离得最近的元素13
那么序列(7,10,13,16,19)中
在left(13)左边的元素都比查找元素值(12)小在right(10)右边的元素都比查找元素值(12)大
回顾这一步的变化,三个指针从都指向10,到两个指向10,另一个指向10在序列中的前驱或者后继。
这个过程已经是二分查找最终端时候地一小步,但它仍然很好的反映了二分查找地本质,就是利用两边的left和right指针控制两个范围,一个是比查找元素值小的,一个是比查找元素值大的。
而我们每次随机在他们范围的交集(为了方便,我们直接取的中间元素mid),这个值就有概率成为我们要查找的值!
显然我们可以不取mid,但由于对称性,在不考虑特殊分布的数据情况下,取mid是成本期望最低的方法。
当两个范围交集为空时,显然我们就失去了取mid的机会了,概率变为了0。
当查找成功时,结论的正确性就很显然了。