next_permutation/prev_permutation详解

来源:互联网 发布:php __get 编辑:程序博客网 时间:2024/06/13 01:55

Next_permutation:按照升序全排列

源码:

// TEMPLATE FUNCTION next_permutation

template<class _BidIt> inline

bool _Next_permutation(_BidIt _First, _BidIt _Last)

{ // permute and test for pure ascending, using operator<

_BidIt _Next = _Last;

if (_First == _Last || _First == --_Next)

return (false);

for (; ; )

{ // find rightmost element smaller than successor

_BidIt _Next1 = _Next;

if (_DEBUG_LT(*--_Next, *_Next1))//相邻两者两两比较,如果后者大于前者,则认为

//找到了需要排序的点,

{ // swap with rightmost element that's smaller, flip suffix

_BidIt _Mid = _Last;

for (; !_DEBUG_LT(*_Next, *--_Mid); );//然后寻找排序点后比当前排序点更大值

_STD iter_swap(_Next, _Mid);//将前者排序的点和后者第一组小的元素交换.这样

_STD reverse(_Next1, _Last);//逆排序

return (true);

}

if (_Next == _First)

{ // pure descending, flip all

_STD reverse(_First, _Last);

return (false);

}

}

}

函数的整个外循环就是从_Last开始往前找,直到找到两两相邻中前者较小的元素_i.然后进行内层循环扫描,寻找比当前相邻较小元素更大的元素_Mid.然后交换找到的元素_Mid与_Next.至此,_First-_Next这部分元素已经满足要求了.只是_Mid-_Last这段元素是_Mid-Last序列中的降序排列(为什么这里的元素是降序排列?因为经过外层循环两两比较和内层循环查找比_Next最大的元素并交换之后,如果不满足降序条件是不切实际的).

这里可以使用如下定理:

b > c
a > b

则a > b > c(即升序也就是_Next1-_Last降序).

需要记住的一点是,程序返回的是比_First-_Last中的更大(刚好更大)的序列.

这个函数似乎也在启示我们,在需要获取几个数的全排列,我们可以现将序列排序,然后利用这个函数来解决.

函数的最后一个判断_Next == _First,则说明容器的最大序列就是本身.但此时即使返回的false,容器的元素顺序也改变了.变成了最小序列.

Prev_permutation:next_permutation相对.

// TEMPLATE FUNCTION prev_permutation

template<class _BidIt> inline

bool _Prev_permutation(_BidIt _First, _BidIt _Last)

{ // reverse permute and test for pure descending, using operator<

_BidIt _Next = _Last;

if (_First == _Last || _First == --_Next)

return (false);

for (; ; )

{ // find rightmost element not smaller than successor

_BidIt _Next1 = _Next;

if (_DEBUG_LT(*_Next1, *--_Next))

{ // swap with rightmost element that's not smaller, flip suffix

_BidIt _Mid = _Last;

for (; !_DEBUG_LT(*--_Mid, *_Next); )

;

_STD iter_swap(_Next, _Mid);

_STD reverse(_Next1, _Last);

return (true);

}

if (_Next == _First)

{ // pure ascending, flip all

_STD reverse(_First, _Last);

return (false);

}

}

}

有了前一个函数,后一个函数就简单多了.注意红色部分.

举例:

int main()

{

vector<int> vecInt;

vecInt.push_back( 1 );

vecInt.push_back( 2 );

vecInt.push_back( 3 );

vecInt.push_back( 4 );

while( next_permutation( vecInt.begin(),vecInt.end() ) )

{

cout<<"\n";

copy( vecInt.begin(),vecInt.end(),ostream_iterator<int>( cout," " ) );

}

cout<<"\nvecInt元a素?的?最?小?的?序ò列为a:";

copy( vecInt.begin(),vecInt.end(),ostream_iterator<int>( cout," " ) );

system( "pause" );

return 0;

}

原创粉丝点击