二分查找(浅谈)

一,概念

       二分查找是将数组a [n]的中的N个元素分成大致相等的两部分,取A [N / 2]与待查找值X做比较,如果:

            (1)X = a [N / 2],则找到X

            (2)X <a [N / 2],则只要在数组左半部分继续搜索。

            (3)X> a [N / 2],则只要在数组右半部分继续搜索。

   

    图示:

        二分法简而言之就是一种能够快速缩小查找范围的查找方法,每次都是比较目标值与中值的大小,再缩小范围,看是查找左半部分还是右半部分,再以缩小范围后的区间中值为起点查找,只到找到目标值为止。 

 

例:给定一个数组a [101] = {0,1,2,..... 100},求每个元素需通过多少次二分查找才能被找到的次数

       代码:

//程序目的,求0 1 ... 99 100 这个数组中每个元素需几次二分查找才能找到的次数 
#include<iostream>
using namespace std;
int main() {
	for(int i=0; i<=100; i++) {
		//左右区间的范围 
		int left=0,right=100;
		//中间值,即查找的起点 
		int mid;
		//查找所需的次数 
		int cont=0;
		//当左区间小于右区间,说明还有数没查找过的时候 
		while(right>=left) {
			//次数增加 
			cont++;
			//初始化起点的位置 
			mid=(left+right)/2;
			//如果该值小于中间值,则缩小区间至[l,mid-1]
			if(i<mid) {         
				right=mid-1;	
			} 
			//如果该值大于中间值,则缩小区间至[mid+1,r]
			else if(i>mid) {  
				left=mid+1; 
			} 
			//如果猜中,跳出
			else {
				break;          
			}
		}
		cout<<i<<"    "<<"一共查找了"<<cont<<"次"<<endl;
	}
	return 0;
}

运行结果:

运行结果显示,元素50只经过一次二分查找就找到了,不难理解,这是因为50处在数组最中间的位置,第一次就找到了它。

 

例:从一个数组中找到两个数,使其和为一个指定的数。
       遍历数组对每一个a[i],通过二分查找找到另一个a[mid]通过两者之和与目标值m的比较决定缩小区间的范围
       这里稍微做了一点变形即将m = a [i] + a [mid]变形为a[mid] = m-a [i],这就符合了二分法的定义。

       代码:


#include<iostream>
#include<algorithm>
using namespace std;
int main() {
	long a[100000],n,m,i,j;
	//标记变量
	bool flag=false;
	cin>>n;
	for(i=0; i<n; i++) {
		cin>>a[i];
	}
	//目标值m
	cin>>m;
	//将数组排好序
	sort(a,a+n);
	//遍历数组当且仅当没找到目标值时
	for(i=0; i<n; i++) {
		//查找区间为[i+1,n-1]
		int l=i,r=n-1;
		while(l<r) {
			int mid=(r+l)/2;
			//当找到目标值且不重复时 
			if(m-a[i]==a[mid]&&i!=mid) {
				flag=true;
				cout<<a[i]<<" "<<a[mid]<<endl;
				break;
			}
			//否则缩小范围到[mid+1,r]
			else if(m-a[i]>a[mid]) {
				l=mid+1;
			} else {
				r=mid-1;
			}
		}
	}
	//如果没找到
	if(flag==false) {
		cout<<"No"<<endl;
	}
	return 0;
}

运行结果:

 

         

 

二,局限

       任何一种算法都有其局限性。二分查找一般来说仅适用于一个元素基本有规律的数组查找,这样才能体现它的快速,当待查找数组毫无规律时,若不排序,二分查找也就失去了它的快速特点。

 

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值