概述
二分查找又称折半查找,是一种效率较高的查找方法。
使用条件
1.必须满足顺序储存结构
2.必须满足元素有序排列
3.必须满足储存结构中元素互异
原理
由于数组元素的有序性和互异性,通过下标得到数组内元素间相对的大小关系,定义三个变量:两个边界变量确定查找范围,一个取值两个边界变量中间值的中间变量用于同被查找值比较大小、从而改变边界变量的值进而缩小查找区间的范围、重新确定中间值,并重复这一过程直到中间值下标等于查找值、最小值下标大于最大值下标,退出循环。
二分查找的流程(正序)
1.使用整型数据数组储存正序排列的互异元素
int[] arr1 = {1,2,3,4,5,6,7,8,9};
2.获取查找数据
//使用Scanner获取输入的数据
Scanner sc = new Scanner(System.in);
int num = sc.nextInt();
3.定义最大值下标、最小值下标、中间值下标
//最大值下标
int maxIndex = arr1.length - 1;
//最小值下标
int minIndex = 0;
//中间值下标
int midIndex = (maxIndex + minIndex) / 2;
4.因为不确定循环次数所以使用while循环
while(true){
//正序排列下,查找数据大于中间值数据
if(arr1[midIndex] < num){
//最小值下标 = 中间值下标 + 1
minIndex = midIndex + 1;
}
//正序排列下,查找数据小于中间值数据
else if(arr1[midIndex] > num){
//最大值下标 = 中间值下标 - 1;
maxIndex = midIndex - 1;
}
else{
break;
}
//正序条件下,最小值下标大于最大值下标时
if(minIndex > maxIndex){
midIndex = -1;
break;
}
//更新中间下标变量
midIndex = (minIndex + maxIndex) / 2;
}
System.out.println(midIndex > 0 ? "找到元素下标为"+midIndex : "找不到该元素!");
初始状态下的三个坐标变量值固定的,不会随着查找数据的改变而改变。如图所示:
执行while循环中的方法体时,我们需要特别注意中间下标值和查找值大小的关系、即不同大小关系对应的执行体,例如:
当查找数据为6时,查找值大于中间下标值,最小值下标变量 = 中间值下标变量 + 1,此时三变量下标值关系:
最小下标变量大于最大下标变量关系不成立,最大下标变量加最小下标变量的和除2的商赋值给中间变量,此时三变量下标值关系:
查找值小于中间下标值,最大值下标变量 = 中间值下标变量 - 1,此时三变量下标值关系:
最小值下标变量大于最大值下标变量关系依然不成立,最大下标变量加最小下标变量的和除2的商赋值给中间变量,此时三变量下标值关系:
中间下标值既不大于、也不小于查找值,退出循环。
二分查找的流程(倒序)
流程和正序相同,我们只说不一样的部分:
1.源数据倒序
int[] arr2 = {9,8,7,6,5,4,3,2,1};
2.倒序情况下,最大值下标变量、最小值下标变量与正序的赋值相反,中间值的赋值运算不变。
//最小值下标
int minIndex = arr2.length - 1;
//中间值下标
int midIndex = (maxIndex + minIndex) / 2;
倒序情况下,初始三下标变量的关系如下:
3.倒序情况下,当最大值下标变量大于最小值下标变量时,查找数据不存在,这与正序条件相反。
if(maxIndex > minIndex){
midIndex = -1;
break;
}
4.倒序情况下,同样采用while循环,中间下标值和查找值的大小关系条件不变,但不同大小关系对应的方法体与正序的情况不同,举例说明:
当查找数据为6时,查找值大于中间下标值,最小值下标变量 = 中间值下标变量 - 1,此时三变量下标值关系:
最大值下标变量大于最小值下标变量的关系不成立,最大值下标变量加最小值下标变量的和除2的商赋值中间下标变量。此时三变量下标值关系:
查找值大于中间下标值,最大值下标变量 = 中间值下标变量 + 1,此时三变量下标值关系:
最大值下标变量大于最小值下标变量的关系不成立,最大值下标变量加最小值下标变量的和除2的商赋值中间下标变量。此时三变量下标值关系:
查找值仍小于中间下标值,最大值下标变量 = 中间值下标变量 + 1
最大值下标变量大于最小值下标变量的关系不成立,最大值下标变量加最小值下标变量的和除2的商赋值中间下标变量。此时三变量下标值关系:
中间下标值既不大于、不小于查找值时,退出循环。