バイナリ検索(C ++の例)

バイナリ検索

例:Aは頭の中で1から1000までの数字を考え、Bは推測し、質問をすることができ、Aは「はい」または「いいえ」にしか答えることができません。質問の最小数を推測する方法は?

  1. 順次検索:1ですか?2ですか?…999ですか?平均500回質問してください
  2. バイナリ検索:500より大きいですか?750より大きいですか?625より大きいですか?…推測範囲を前回の半分に減らすのに10回しかかかりません
  3. バイナリ検索の内容は順番になっている必要があります。

例1:関数BinarySeachを記述して、サイズ要素を含むint配列内の要素pを検索し、見つかった場合は小さいものから大きいものへと並べ替え、見つかった場合は要素インデックスを返し、見つからなかった場合は-1を返します。複雑さO(log(n))が必要です。

コード:

int BinarySeach(int a[],int size,int p){
    
    
	int L = 0;	//查找区间的左端点
	int R = size - 1;	//查找区间的右端点
	while(L <= R){
    
    	//如果查找区间不为空就继续查找 
		int mid = L+(R-L)/2;	//取查找区间正中元素的下标 
		if(p == a[mid])
			return mid;
		else if(p > a[mid])	//说明p在a[]的左半部 
			L = mid + 1;	//重置查找区间的左端点 
		else 
			R = mid - 1;	// 重置查找区间的右端点
	}
	return -1;
}	

例2:関数LowerBoundを記述して、サイズ要素を含み、小さいものから大きいものへとソートされたint配列a内の指定された整数pよりも小さい最大の添え字を持つ要素を検索します。見つかった場合はその添え字を返し、見つからなかった場合は-1を返します。

コード:

int LowerBound(int a[],int size,int p){
    
    
	int L = 0;	//查找区间的左端点 
	int R = size - 1;	//查找区间的右端点 
	int lastPos = -1;	//目前为止找到的最优解 
	while(L <= R){
    
    	//如果查找区间正中元素的下标
		int mid = L+(R-L)/2;	//去查找区间正中元素的下标
		if (a[mid] >= p)
			R = mid - 1;
		else{
    
    
			lastPos = mid;
			L = mid+1;
		}
	}
	return lastPos;
}

注:
int mid = (L+R)/2; //取查找区间正中元素的下标
(L + R)がオーバーフローしすぎないようにするには:
int mid = L+(R-L) /2;


例3:二分法による方程式の根の検索
次の方程式の根を検索します。f(x)= x 3 -5x 2 + 10x-80 = 0;検出される根がaの場合、| f(a)| < = 10-6

解決策:f(x)の導関数を取り、f '(x)= 3x 2 -10x +10を取得します。1つの変数で2次方程式の根を見つけるための式は、方程式f '(x)= 0には解がないことを知っているため、f'(x)は常に0より大きくなります。したがって、f(x)は単調に増加しています。f(0)<0およびf(100)> 0であることは簡単にわかります。したがって、間隔[0、100]にはルートが1つだけ存在する必要があります。f(x)は[0、100]で単調であるため、二分法を使用して[0、100]の間隔でルートを見つけることができます。

コード

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;

double EPS = 1e-6;
double f(double x){
    
    
	return x*x*x - 5*x*x + 10*x - 80; 
}
int main(){
    
    
	double root, x1 = 0,x2 = 100,y;
	root = x1+(x2-x1)/2;
	int triedTimes = 1;//记录一共尝试多少次
	y = f(root);

	while( fabs(y) > EPS){
    
    
		if(y > 0)
			x2 = root;
		else 
			x1 = root;
		root = x1+(x2-x1)/2;
		y = f(root);
		triedTimes++;
	}
	printf("%.08f\n",root);
	printf("%d",triedTimes);
	return 0;
} 

おすすめ

転載: blog.csdn.net/qq_44524918/article/details/108856751