二分法,也叫做折半法,就是一种通过有序表的中间元素与目标元素进行对比,根据大小关系排除一半元素,然后继续在剩余的一半中进行查找,重复这个过程直至找到目标值或者确定目标值不存在。
我们从结论往回推,判断其条件为什么这么写。
先看代码:
void search(int[] A,int x){ int low=0,high=n-1,mid; while(low<=high){ mid = (low+high)/2; if(A[mid] == x)break; else if(A[mid] < x) //目标元素在当前中间元素的右边 low = mid+1; else//目标元素在当前中间元素的左边 high = mid-1; }if(low > high)//未找到 return;
}
难点无非在于两个问题:
mid=(low+high)/2
的问题。- 为什么设定low<=high为符合条件,low>high为不符合条件?
首先说第一个问题,因为int类型在做除法运算时,如果结果不为整数,则会向下取舍,所以7/2=3,9/2=4。这个问题取决了本问题中的mid会指向哪个元素:
当顺序表元素个数为奇数时:
mid=(0+6)/2=3
当顺序表元素个数为偶数时:
mid= (0+7)/2=3
- 当目标元素>mid时,low移动到mid右边;
- 当目标元素<mid时low移动到mid左边;
- 当目标元素==mid时退出循环。
根据以上步骤,假设查找元素为x,我们可以得到:
元素个数为奇数时
当元素个数为偶数时
边界情况(目标元素在表头或表尾)
可以发现,在边界情况下,当low==high时,mid也依旧再移动一次才能找到指定元素。所以循环条件必须要带上=。
找不到的情况
可以发现,在最后一次查找中,三个指针会指向同一个元素,而代码中比较完紧随其后的就是移动指针,图画中x>5,所以low会向右移动一个元素,此时两个箭头出现了交叉,确定了该有序表中没有目标元素。所以不符合的条件为low>high。