STL 生成全排列

在看陈硕的Linux多线程服务器编程时 ,看到生成全排列的一种方式,使用stl的next_permutation方法,正好手上有本stl源码剖析,就研究了下这个算法。

template<class 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 t = i;
        --i;
        if(*i < *t) {
            BidirectionalIterator j = last;
            while(!(*i < *--j));

            iter_swap(i, j);
            reverse(t, last);
            return true;
        }
        
        if(i == first) {
            reverse(first, last);  //全逆向,即为最小字典序列,如cba变为abc
            return false;
        }
    }
}

  当还能生成下个排列时,返回true,如果不能在生成了,返回false。

这是其实现方式,主要思想就是:从后往前查找相邻的迭代器 i和ii,并使得*i<*ii;再从后往前查找第一个大于i值的迭代器j,将i和j所指内容交换,并将ii到last的内容翻转。

如果i到了begin,且(*i>=*ii),那么说明不能在生成下个排列了,返回false。

利用这个算法生成全排列:

#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;
}

 

下面自己根据此思想生成的一个方式:

// GetAllPartition.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <VECTOR>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;

static int num = 0;
void getallpartition(vector<int> & v){
    vector<int>::iterator i = v.end();
    vector<int>::iterator ii;
    ostream_iterator<int> outite(cout," ");
    copy(v.begin(),v.end(),outite);
    cout<<endl;
    num++;

    for(;;){
        i = v.end();
        --i;
        ii = i;
        --i;
        while(!(*i < *ii) ){
            --i;
            --ii;
            if( i == v.begin() && (*i > *ii)){
                return;
            }
        }
        if(*i < *ii){
            vector<int>::iterator j = v.end();
            while(!(*i < *--j));
            iter_swap(i,j);
            reverse(ii,v.end());
            copy(v.begin(),v.end(),outite);
            cout<<endl;
            num++;
        }
    }
}

int main(int argc, char* argv[])
{
    int array[] = {1,2,3,4,5};
    vector<int> v(array,array+sizeof(array)/sizeof(int));
    getallpartition(v);
    cout<<num<<endl;
    return 0;
}

附:

iter_swap(iteri,iterj); // 将iteri和iterj所指内容交换

{

  T tmp = *iteri;

  *iteri = *iterj;

  *iterj = tmp;

}

 

void reverse(BidirectionlIterator first,BidirectionlIterator last);
//双层架构,对BidirectionlIterator和RandomAccessIterator版本
template<class BidirectionlIterator>
inline void reverse(BidirectionlIterator first,BidirectionlIterator last){
    _reverse(first,last,iterator_category(first));
}

template<class BidirectionlIterator>
void _reverse(BidirectionlIterator first,BidirectionlIterator last,bidirectional_iterator_tag){
    while(true){
        if(first == last || first == --last )
            return;
        else
            iter_swap(first++,last);
    }
}

template<class RandomAccessIterator>
void _reverse(RandomAccessIterator first,RandomAccessIterator last,random_access_iterator_tag){
    while(first < last)       //Randomaccessiterator才支持<运算符,从而针对这个版本提高了效率
        iter_swap(first++,--last);
}

 

posted @ 2015-08-14 20:59  朽木可雕否  阅读(288)  评论(0编辑  收藏  举报