一、问题描述:给定n个元素,这些元素是有序的,从数组中查找特定的元素x。
个人觉得二分法搜索是分治法里面最简单的一个搜索算法了,就是设置一个下界low和上界high,然后再设一个指针mid ( mid=(low+high)/2 ),然后随着每次搜索mid会在两个区间之间( [low,mid-1] 和 [mid+1,high] )进行移动,对应的,low或者high也要相应地改变位置。**要注意这里mid是数组下标而不是一个值。**如图:
具体一点,就拿上面这个例子来说:首先,二分查找是要在有序的条件下进行的,习惯就先把数组定为升序吧(调用sort()函数即可)。然后初始化完成之后,先判定low<=high是否成立,是,则判断要找的元素x跟mid所对应的数组元素的值是否相等(之后详见算法);否,则算法结束。
二、核心算法:
int BinarySearch(int n, int s[], int x){
//n代表元素个数,s[]代表有序数组,x为特定查找元素
int low = 0;
int high = n-1;
while (low <= high){
int mid = (low+high)/2;
if(x == s[mid]){
return s[mid];
} else if(x < s[mid]){
//从前半部分查找
high = mid-1;
} else if(x > s[mid]){
//从后半部分查找
low = mid+1;
}
}
return -1;
}
继续思考,还有一种递归的方法可以用来表示二分搜索,代码如下:
int RecursionBS(int s[], int x, int low, int high){
if(low > high){
return -1;
}
int mid = (low + high )/2;
if(x == s[mid]){
return mid;
}else if(x < s[mid]){
return RecursionBS(s, x, low, mid - 1);
}else if(x > s[mid]){
return RecursionBS(s, x, mid + 1, high);
}
} //注释可以参考上面的非递归注释,是一样的
好了,那么结合到实例中的算法:
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
using namespace std;
const int M = 1005;
int x,n,i;
int s[M];
int BinarySearch(int n, int s[], int x){
//n代表元素个数,s[]代表有序数组,x为特定查找元素
int low = 0;
int high = n-1;
while (low <= high){
int mid = (low+high)/2;
if(x == s[mid]){
return s[mid];
} else if(x < s[mid]){
//从前半部分查找
high = mid-1;
} else if(x > s[mid]){
//从后半部分查找
low = mid+1;
}
}
return -1;
}
int main( void ) {
cout<<"数组中的元素个数为:"<<endl;
while(cin >> n){
cout<<"请依次输入数组中的元素:"<<endl;
for(i=0; i<n; i++){
cin >> s[i];
}
sort(s,s+n);
cout<<"排好序的数组如下:"<<endl;
for(i=0; i<n; i++){
cout<<s[i]<<" ";
}
cout<<"请输入要查找的元素:";
cin >> x;
i = BinarySearch(n,s,x);
if(i == -1){
cout<<"没有该元素"<<endl;
}
else {
cout<<"该元素在第"<<i+1<<"位"<<endl;
}
}
return 0;
}
时间复杂度为:O(nlogn)
其实感觉不论什么算法,细节都还是挺多的,特别是关于数组的,下标比较容易出错,特别是要能敲出来并且正确运行,所以还得细心,实在有点不理解就画图吧 [doge]
(原创不易,点个赞再走吧~)