目录
转自:https://blog.csdn.net/u011787119/article/details/44598871
https://www.cnblogs.com/ECJTUACM-873284962/p/6536414.html
一、概念
在二分查找的基础上,在右区间(或左区间)再进行一次二分,这样的查找算法称为三分查找,也就是三分法。
三分查找通常用来迅速确定最值。
二分查找所面向的搜索序列的要求是:具有单调性(不一定严格单调);没有单调性的序列不是使用二分查找。
与二分查找不同的是,三分法所面向的搜索序列的要求是:序列为一个凸性函数。通俗来讲,就是该序列必须有一个最大值(或最小值),在最大值(最小值)的左侧序列,必须满足不严格单调递增(递减),右侧序列必须满足不严格单调递减(递增)。如下图,表示一个有最大值的凸性函数:
二、算法过程
如图所示,已知左右端点L、R,要求找到某点的位置。
思路:通过不断缩小 [L,R] 的范围,无限逼近白点。
做法:先取 [L,R] 的中点 midl,再取 [mid,R] 的中点 midr,通过比较 f(midl) 与 f(midr) 的大小来缩小范围。
当最后 L=R-1 时,再比较下这两个点的值,我们就找到了答案。
1、当 f(midl) > f(midr) 的时候,我们可以断定 mmid 一定在白点的右边。
反证法:假设 mmid 在白点的左边,则 mid 也一定在白点的左边,又由 f(midl) > f(midr) 可推出 midl < midr,与已知矛盾,故假设不成立。
所以,此时可以将 R = midr 来缩小范围。
2、当 f(midl) < f(midr) 的时候,我们可以断定 mid 一定在白点的左边。
反证法:假设 midl 在白点的右边,则 midr 也一定在白点的右边,又由 f(midl) < f(midr) 可推出 midl > midr,与已知矛盾,故假设不成立。
同理,此时可以将 L = midl 来缩小范围。
三、代码
double f(double x)
{
// 计算函数值,即f(x)
}
double trisection_search(double left, double right)
{
// 三分搜索,找到最优解(求函数最大值下的自变量值)
double midl, midr;
while (right-left > 1e-7)
{
midl = (left + right) / 2;
midr = (midl + right) / 2;
// 如果是求最小值的话这里判<=即可
if(f(midl) >= f(midr)) right = midr;
else left = midl;
}
return left;
}