简单算法——二分查找法
程序员文章站
2022-03-08 23:39:46
...
二分查找算法二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。
但是,前提是查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。
查找过程
首先,假设数组中元素是按升序排列,将数组中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将数组分成前、后两个子数组,如果中间位置记录的关键字大于查找关键字,则进一步查找前一数组,否则进一步查找后一数组。重复以上过程,直到找到满足条件的记录,使查找成功,或直到数组不存在为止,此时查找不成功。
下面我们测试一下:
/**
* 二分查找
* @param arr 元素组
* @param num 查询数据
* @return 返回脚标
*/
public static int binarySearch(int [] arr,int num){
//起始脚标
int start = 0;
//末尾脚标
int end = arr.length -1;
while(start <= end){
//获取中间脚标
int middleindex = (start+ end)/2;
// 拿中间位置数据 与传递数据进行比较
if(num < arr[middleindex]){
//如果中间位置数据 大于当前数据 则将end 设置为中间位置减一
end = middleindex - 1;
}else if(num > arr[middleindex]){
//如果中间位置数据 大于当前数据 则将start 设置为中间位置加一
start = middleindex+1;
}else {
//等于 直接命中 返回脚标
return middleindex;
}
}
return -1;
}
/**
* 普通查找
* @param arr 元素组
* @param num 查询数据
* @return 返回脚标
*/
public static int simpleSearch(int [] arr,int num){
for (int i = 0; i < arr.length; i++) {
if(arr[i] == num ){
return i;
}
}
return -1;
}
- 设定起始查询脚标为0,结束脚标为数组长度减一。
- 将数据进行循环,首次获取中间位置(int 会强制转换成整数型,不用担心除不尽)。
- 拿中间位置数据 与传递数据进行比较 如果中间位置数据 大于当前数据 则将end 设置为中间位置减一
- 如果中间位置数据 大于当前数据 则将start 设置为中间位置加一
- 等于 直接命中 返回脚标
创建一个200000000大小的数组测试一下和普通查询的效率差距:
//创建一个200000000大小的数组
public static void main(String[] args) {
int [] arr = new int[200000000];
for (int i = 0; i < 200000000; i++) {
arr[i] = i ;
}
Arrays.sort(arr);
Instant startTime = Instant.now();
int i = binarySearch(arr, 190000000);
Instant endTime = Instant.now();
System.out.println(i);
System.out.println("二分查询:" +Duration.between(startTime,endTime).toMillis()+"ms");
Instant start = Instant.now();
int i1 = simpleSearch(arr, 190000000);
System.out.println(i1);
Instant end = Instant.now();
System.out.println("遍历查询:" + Duration.between(start,end).toMillis()+"ms");
}
190000000
二分查询:0ms
190000000
遍历查询:82ms
可以看到差距比想象中打的惊人。
因为:二分查找的基本思想是将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果xa[n/2],则只要在数组a的右半部搜索x.
时间复杂度无非就是while循环的次数!
总共有n个元素,
渐渐跟下去就是n,n/2,n/4,…n/2^k(接下来操作元素的剩余个数),其中k就是循环的次数
由于你n/2^k取整后>=1
即令n/2^k=1
可得k=log2n,(是以2为底,n的对数)
所以时间复杂度可以表示O(h)=O(log2n)。
上一篇: 关于链表的清空(防止内存泄漏)
下一篇: 简单算法(2)二分查找