对范型算法next_permutation的源码分析

 // TEMPLATE FUNCTION next_permutation
template<class _BI> inline
    bool next_permutation(_BI _F, _BI _L)
    {_BI _I = _L;
    if (_F == _L || _F == --_I)  // (1)
        return (false);
    for (; ; )
        {_BI _Ip = _I;  // (2)
        if (*--_I < *_Ip)   // (3)
            {_BI _J = _L;
            for (; !(*_I < *--_J); )  // (4)
                ;
            iter_swap(_I, _J);  // (5)
            reverse(_Ip, _L);  // (6)
            return (true); }
        if (_I == _F)
            {reverse(_F, _L);  // (7)
            return (false); }}}

next_permutation()将[first,last)标记的排列重排为下一个排列,如果不存在下一个排列,则返回false。
源码分析(假设有容器{3,5,4,2}):
(1)、由于范型算法一般是应用在容器上,而容器是用其首元素和最后元素的下一个位置来表示其范围的,所以next_permutation()处理的 [first,last)为半开半闭区间,对于算法内部,则很明显要先对_I进行递减操作,使其指向容器的最后一个元素,如果和首元素地址相同,则为单元素容器,不存在下一个排列。
(2)、把_I的iter赋给_lp,注意对于第一次循环_I是指向最后元素了(因为(1)中有操作--I)。_Ip和_I指向容器元素5时,(3)的条件满足。
(3)、因其处在无限循环for(;;)中,故在容器中从后往前找第一个非逆序(后面的元素不小于其紧挨的之前的元素*--I<*_lp)(3,5),此时_I指向3,_lp指向5。
(4)、对_I到最后一个元素之间的元素查询是否有大于_I所指向的元素(3),有!此时_J指向元素5大于3。如果没有,那么该for循环最后_I,_J指向同一元素3,同样结束该for循环。
(5)、交换_I,_J所指向的元素。得到容器{4532}
(6)、对于_lp和_L之间的元素重新按反序排列,原来为逆序532,现在重排为235,于是得到容易{4235}  ,即是容器{3542}的下一个排列。
(7)、对于已经排成完全逆序的容器,如{5432},则先将其按反序重排为完全顺序{2345},然后返回false,因为其不存在下一个排列。

注意:在求容器的下一个排列时,总是要保证容器靠前的元素最小的不同排列,且如果得到完全逆序容器,则返回false,所以如果要求一个容器的全排列,应该先对该容器进行顺序排序,最后一点经过next_permutation()操作最后返回false后的容器为顺序的,应为该算法对完全逆序容器是先反序排列了之后再返回false的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值