数学是科学的皇冠,这句话一点也不假,在程序的算法应用上也是这样的。
众所周知,当数据量很大的时候,采用二分法是非常高效的(使用二分法查找的前提是数据是排好序的,这里不作讨论)。二分法查找的原理来自于数学上的函数的零点问题,也就是求函数的近似值(近似解)。
引用我们的高中数学教材的必修一里面的内容:求f(x)的近似解,通过试验知函数f(x)在区间(a,b)上存在零点。如何找出这个零点?一个直观的想法就是,尽可能的把零点的邻域缩小,当足够小的时候,就可以用近似值代替函数的零点。下面给出步骤
1、确定区间[a,b],验证f(a)*f(b)<0,给定精度**ε**。
2、求(a,b)的中点c。
3、计算f(c)。
0)若f(c)=0,则c就是零点
1)若f(a)*f(c)<0,令b=c,此时零点在(a,c)区间上,
2)若f(c)*f(b)<0,令a=c,此时零点在(c,b)区间上,
4、验证精度是否达到要求,若|a-b|<**ε**,即零点的近似值为a(或者b),若不成立,重复2-4步骤。
下图是函数f(x)=lnx+2x-6求求近似解的示例
那么,这种每运算一次把问题减少一半的思想,就可以运用到我们的搜索算法去,即将n个元素分成大致相等的两部分,取a[n/2]与x做比较,如果x=a[n/2],则找到x,算法中止;如果x<a[n/2],则只要在数组a的左半部分继续搜索x,如果x>a[n/2],则只要在数组a的右半部搜索x。当数据量很大的时候,这种方法就体现出它的威力来了,下面给出c++的代码(偷懒一下,百度来的)
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int a[100]={1,2,3,5,12,12,12,15,29,55};//数组中的数(由小到大)
int k;//要找的数字
int found(int x,int y)
{
int m=x+(y-x)/2;
if(x>y)//查找完毕没有找到答案,返回-1
return -1;
else
{
if(a[m]==k)
return m;//找到!返回位置.
else if(a[m]>k)
return found(x,m-1);//找左边
else
return found(m+1,y);//找右边
}
}
int main()
{
cin>>k;//输入要找的数字c语言把cin换为scanf即可
cout<<found(0,9);//从数组a[0]到a[9]c语言把cout换为printf即可
return 0;
}
高一所学的数学都能在算法上发挥如此大的威力,不得不感叹,数学真美。