以一个有序数列查找其中的数为例;二分查找能把 O ( n ) 的时间复杂度降到O(log n),大大减小了时间复杂度;
#include
using namespace std;
//a[] 为严格递增序列,left为二分下界,right为二分上界,x为欲查询的数
//二分区域为左闭右闭的[left,right],传入的初值为[0,n-1]
int binarysearch(int a[],int left,int right,int x) {
int mid;
while(left<=right) { // 如果left>right 就没办法形成闭区间了
mid=(left+right)/2;// 取中点
if(a[mid]==x) return mid;//找到mid 返回下标
else if(a[mid]>x) {//往左子区间[left,mid-1]查找
right=mid-1;
} else {//中间的数小于x
left=mid+1;//往右子区间 [mid+1,right]查找。
}
}
return -1;//查找失败返回-1;
}
int main() {
const int n=10;
int a[n]= {1,3,4,6,7,8,10,11,12,15};
printf("%d %d",binarysearch(a,0,n-1,6),binarysearch(a,0,n-1,9));
return 0;
}
如果有重复的数字,可以简单拓展一下如下。
#include
using namespace std;
//a[]为递增序列,x为欲查找的数,函数返回第一个大于等于x的元素的位置
//二分上下界为左闭右闭的[left,right] ,传入的值为[0,n]
int lower_bound(int a[],int left,int right,int x){
int mid;//mid为left和right的中点
while(left<right){
mid=(left+right)/2;//取中点
if(a[mid]>=x){//中间的数大于等于x
right=mid;//往左区间[left,mid]查找
}else{//中间的数小于x
left=mid+1;//往右子区间[mid+1,right]查找
}
}
return left;//返回夹出的位置
}
int main(){
const int n=11;
int a[n]={1,3,4,6,7,7,7,8,10,11,12};
printf("%d",lower_bound(a,0,n,7));
return 0;
}
#include
using namespace std;
//a[]为递增序列,x为欲查找的数,函数返回第一个大于x的元素位置
//二分上下界为左右闭的[left,right],传入的初值为[0,n]
int upper_bound(int a[],int left,int right,int x) {
int mid;// mid为left和right的中点
while(left<right) {
mid=(left+right)/2;//取中点
if(a[mid]>x) { //中间的数大于x
right=mid;//往左子区间[left,mid]查找
} else { //中间的数小于等于x
left=mid+1;//往右子区间[mid,right]查找
}
}
return left;//返回夹出来的数
}
int main() {
const int n=11;
int a[n]= {1,3,4,6,7,7,7,8,10,11,12};
printf("%d",upper_bound(a,0,n,7));
return 0;
}