数据结构 查找 二分查找与三分查找

有序条件下,才能查找算法

一.二分查找数组

(具备单调性,不必定严格单调)函数

(min 与max 是查找区间,经过不断缩小查找区间,来查找x的值)指针

min是头指针; max是尾指针;mid = (min + max) / 2;code

终止条件:min >= maxio

若是arr[mid] < x, min = mid + 1;ast

若是arr[mid] > x, max = mid - 1;class

若是arr[mid] == x, 找到结果基础

1.特殊状况(求最小最大解)搜索

查找最后的1

【min】【1】【1】【1】【1】【1】【0】【0】【0】【0】【0】

mid max

min:虚拟头指针

max:尾指针

mid = (min + max + 1) / 2

调整:

若是arr[mid] == 1, min = mid

若是arr[mid] != 1, max = mid - 1

若是min==max, 找到结果

2.特殊状况(求最小花费)

查找第一个1

【0】【0】【0】【0】【1】【1】【1】【1】【1】【1】【max】

min mid

min:头指针

max:虚拟尾指针

mid = (min + max) / 2

调整:

若是arr[mid] == 1,min = mid + 1;

若是arr[max] != 1, max = mid;

若是min==max,找到结果

二.三分查找

每次搜索范围缩小三分之一

求凹凸函数的极值问题

在二分查找的基础上,在右区间(或左区间)再进行一次二分,这样的查找算法称为 三分查找,也就是三分法。

三分查找一般用来迅速肯定最值。

(1)mid = (left + right) / 2;

(2)取右侧区间的中间值midmid,把区间分为三个小区间;midmid = (mid + right) / 2;

(3)比较mid与midmid谁最靠近最值,只须要肯定mid所在的函数值与midmid所在的函数值的大小。当最值为最大值时,mid与midmid中较大的那个天然更为靠近最值。最值为最小值时同理。

#include <stdio.h>
#include <math.h>

int binary_search1(int *num, int n, int x){
	int min = 0, max = n - 1, mid;
	while(min <= max){
		mid = (min + max) / 2;
		if(num[mid] == x) return mid;
		if(num[mid] < x) min = mid + 1;
		else max = mid - 1;
	}
	return -1;
}

int binary_search2(int *num, int n){//找到最后的1,Eg:11111000
	int min = -1, max = n - 1, mid;//min是虚拟头指针;
	while(min < max){
		mid = (min + max + 1) / 2;//+1防止出现min与mid重合的死循环;
		if(num[mid] == 0) max = mid - 1;//因为要找的是1,能够把后面的数据都扔掉了;
		else min = mid;
	}
	return min;//找不到自动等于-1;
}

int binary_search3(int *num, int n){//找到第一个1,Eg:00011111
	int min = 0, max = n, mid;//max是虚拟尾指针,防止出现死循环;
	while(min < max){
		mid = (min + max) / 2;
		if(num[mid] == 0) min = mid + 1;//因为要找数据1,能够把前面的数据扔掉了;
		else max = mid;
	}
	if(min == n) return -1;//数组中没有1;
	return min;
}

double f(double x){
	static double a = 3.0, b = 2.0, c = 1.0;
	return a * x * x + b * x + c;
}

double ternary_search(double (*func) (double)){
	#define EPSLON 1e-7
	double L = -1000, R = 1000, m1, m2;
	while(fabs(L - R) > EPSLON){
		m1 = (R - L) / 3.0 + L;
		m2 = 2.0 * (R - L) / 3.0 + L;
		if(func(m1) > func(m2)) L = m1;
		else R = m2;
	}
	#undef EPSLON
	return L;
}

int main(){
	int num1[] = {1, 2, 3, 4, 5, 6};
	printf("binary_search1(5): %d\n", binary_search1(num1, 6, 5));
	int num2[] = {1,1,1,1,1,1,1,1,0,0,0,0,0,0,0};
	printf("binary_search2(last one): %d\n", binary_search2(num2, 15));
	int num3[] = {0,0,0,0,0,0,0,1,1,1,1,1,1,1,1};
	printf("binary_search3(first one): %d\n", binary_search3(num3, 15));
	printf("ternary_search(): %lf\n", ternary_search(f));
	return 0;
}

输出结果:

binary_search1(5): 4
binary_search2(last one): 7
binary_search3(first one): 7
ternary_search(): -0.333333