C++之upper_bound的谓词趣用

今天做一道算法题,用到了upper_bound,第一次需要给upper_bound加谓词功能。题中需要比较的是结构体,我就这样调用upper_bound:

/**
 * Definition for an interval.
 * struct Interval {
 *     int start;
 *     int end;
 *     Interval() : start(0), end(0) {}
 *     Interval(int s, int e) : start(s), end(e) {}
 * };
 */
Interval newInterval(2,3);
auto iter=upper_bound(intervals.begin(),intervals.end(),newInterval,[](auto a,auto b){return a.start<=b.end};);

然后我发现用这个谓词起到了lower_bound的效果。
我主要不是想说这道题,我是突然发现,当lower_bound莫名奇妙不起作用的时候,可以试试把upper_bound的谓词换成<=,它和lower_bound的效果是一样的。下面贴一下VC++里 upper_bound的源码实现:

template<class _FwdIt,
    class _Ty,
    class _Pr> inline
    _FwdIt _Upper_bound_unchecked(_FwdIt _First, _FwdIt _Last,
        const _Ty& _Val, _Pr _Pred)
    {   // find first element that _Val is before, using _Pred
    _Iter_diff_t<_FwdIt> _Count = _STD distance(_First, _Last);

    while (0 < _Count)
        {   // divide and conquer, find half that contains answer
        _Iter_diff_t<_FwdIt> _Count2 = _Count >> 1; // TRANSITION, VSO#433486
        const auto _Mid = _STD next(_First, _Count2);
        if (_Pred(_Val, *_Mid))
            {
            _Count = _Count2;
            }
        else
            {   // try top half
            _First = _Next_iter(_Mid);
            _Count -= _Count2 + 1;
            }
        }

    return (_First);
    }

读过源码后是知道了为什么upper_bound把谓词改为<=就可以当upper_bound用了,因为这句话:if (_Pred(_Val, *_Mid)),这里是val在其,mid在后,正常的非模板版本应该是if(nums[mid]>val),所以这里改成<=,就是仅将=的情况划给了upper_bound本该查找的范围,因此就等价于了lower_bound。
但是我还是不明白我直接用lower_bound并且不改谓词,然后又读了一下lower_bound的VC++源码,恍然大悟。

template<class _FwdIt,
    class _Ty,
    class _Pr> inline
    _FwdIt _Lower_bound_unchecked(_FwdIt _First, _FwdIt _Last,
        const _Ty& _Val, _Pr _Pred)
    {   // find first element not before _Val, using _Pred
    _Iter_diff_t<_FwdIt> _Count = _STD distance(_First, _Last);

    while (0 < _Count)
        {   // divide and conquer, find half that contains answer
        _Iter_diff_t<_FwdIt> _Count2 = _Count >> 1; // TRANSITION, VSO#433486
        const auto _Mid = _STD next(_First, _Count2);
        if (_Pred(*_Mid, _Val))//重点
            {   // try top half
            _First = _Next_iter(_Mid);
            _Count -= _Count2 + 1;
            }
        else
            {
            _Count = _Count2;
            }
        }

    return (_First);
    }

if (_Pred(*_Mid, _Val))//重点是这句话,lower_bound的谓词参数是mid在前,val在后的,因此给lower_bound添加谓词,得和upper_bound反过来添加,我把题里的语句改成:

auto iter1=lower_bound(intervals.begin(),intervals.end(),newInterval,[](auto b,auto a){return b.end<a.start;});

问题就迎刃而解了。我觉得VC++源码写成这样,确实方便了它自身的实现,但是很不方便用户的调用,毕竟,在没有读过源码的情况下,谁会认为upper_bound和lower_bound的谓词参数顺序是相反的呢?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值