STL之生成全排列:next_permutation & prev_permutation

来源:互联网 发布:c语言bonus什么意思 编辑:程序博客网 时间:2024/05/13 03:12

源码剖析:

next_permutation:

函数实现原理如下:

在当前序列中,从尾端往前寻找两个相邻元素,前一个记为*i,后一个记为*ii,并且满足*i < *ii。然后再从尾端寻找另一个元素*j,如果满足*i < *j,即将第i个元素与第j个元素对调,并将第ii个元素之后(包括ii)的所有元素颠倒排序,即求出下一个序列了。


template<typename _BidirectionalIterator>bool next_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last){    if (__first == __last)  //空区间        return false;    _BidirectionalIterator __i = __first;    ++__i;    if (__i == __last)  //只有一个元素        return false;    __i = __last;   //指向尾端    --__i;    for(;;)    {        _BidirectionalIterator __ii = __i;        --__i;        //以上,锁定一组(两个)相邻元素        if (*__i < *__ii)        {        //如果前一个元素小于后一个元素            _BidirectionalIterator __j = __last;  //令__j指向尾端            while (!(*__i < *--__j))   //由尾端往前找,直到遇到比*__i大的元素            { }            std::iter_swap(__i, __j);  //交换__i,__j            std::reverse(__ii, __last);  //将 __ii 之后的元素全部逆向重排            return true;        }        if (__i == __first)   //进行到最前面了        {            std::reverse(__first, __last);  //全部逆向重排            return false;        }    }}

prev_permutation:

template<typename _BidirectionalIterator>bool prev_permutation(_BidirectionalIterator __first, _BidirectionalIterator __last){    if (__first == __last)        return false;    _BidirectionalIterator __i = __first;    ++__i;    if (__i == __last)        return false;    __i = __last;    --__i;    for(;;){        _BidirectionalIterator __ii = __i;        --__i;        if (*__ii < *__i)    {            _BidirectionalIterator __j = __last;            while (!(*--__j < *__i))            { }            std::iter_swap(__i, __j);            std::reverse(__ii, __last);            return true;    }        if (__i == __first)    {            std::reverse(__first, __last);            return false;    }}}


测试如下: (可使用string 或 char,int 数组)
#include <cstdio>#include <algorithm>#include <string>#include <iostream>using namespace std;int main(){    int a[10],b[10];    int n;    puts("输入数字个数:");    scanf("%d",&n);    for(int i = 0; i < n; i++)    {        scanf("%d",&a[i]);        b[i] = a[i];    }//    sort(a,a+n);     puts("prev_permutation:");    while(prev_permutation(b,b+n))    {        for(int i = 0; i < n; i++)        {            printf("%d ",b[i]);        }        printf("\n");    }    puts("next_premutation:");    while(next_permutation(a,a+n))    {        for(int i = 0; i < n; i++)        {            printf("%d ",a[i]);        }        printf("\n");    }}
string:

#include <iostream>#include <algorithm>#include <string> using namespace std; int main(){    string str;    cin >> str;    sort(str.begin(), str.end());    cout << str << endl;    while (next_permutation(str.begin(), str.end()))    {        cout << str << endl;    }    return 0;}

对于第三个参数:

对于第二个重载函数的第三个参数,默认比较顺序为小于。如果找到下一个序列,则返回真,否则返回假。

comp
Binary function that accepts two arguments of the type pointed by BidirectionalIterator, and returns a value convertible to bool. The value returned indicates whether the first argument is considered to go before the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.

This can either be a function pointer or a function object.

plusplus:

重排列之后的序列为最小字典列(对于prev反之);

Example

123456789101112131415161718
// next_permutation example#include <iostream>     // std::cout#include <algorithm>    // std::next_permutation, std::sortint main () {  int myints[] = {1,2,3};  std::sort (myints,myints+3);  std::cout << "The 3! possible permutations with 3 elements:\n";  do {    std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';  } while ( std::next_permutation(myints,myints+3) );  std::cout << "After loop: " << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';  return 0;}

Output:
The 3! possible permutations with 3 elements:1 2 31 3 22 1 32 3 13 1 23 2 1After loop: 1 2 3

原创粉丝点击