STL库全排列算法next_permutation

1.next_permutation 函数原型

template<class BidirectionalIterator>  
bool next_permutation(  
      BidirectionalIterator _First,   
      BidirectionalIterator _Last  
);  
template<class BidirectionalIterator, class BinaryPredicate>  
bool next_permutation(  
      BidirectionalIterator _First,   
      BidirectionalIterator _Last,  
      BinaryPredicate _Comp  
 ); 

由函数模板可知,next_permutation返回值为bool型,模板2第三个参数用来表示比较方式,默认形式为小于,当找到下一个全排列序列时返回值为真,若没找到则返回值为假。

(这里解释下何时为找到:对于序列(1,2,3),默认的所有全排列方式为((123),(132),(213),(231),(312),(321)),即当输入为前5个序列时,均能找到下一个排列方式的序列,返回值为真,输入序列为最后(321)时,无下一排列方式序列,返回值为假)


2.next_permutation实现原理

对于一个序列进行全排列,如(123),我们自然会得到((123),(132),(213),(231),(312),(321))所有可能,在书写排列方式的过程中,我们是先将1固定,然后排23,然后2换置第一位,再排13,最后3换置第一位,排12。我们看一个较长的序列(23154),如何找到它下一个序列呢?我们从序列尾部开始依次向前寻找,找到第一个相邻两数(i,ii)满足如下条件i<ii,此处为(1,5);再从尾部开始寻找第一个大于i的数,记为j;交换i,j位置,得到序列(23451),最后,将ii后序列(含ii在内)反转得到序列(23415),此即为(23154)的下一个序列

原理分析:

1.依次向前寻找第一个相邻两个数(i,ii)满足(i<ii):使得ii后数均小于ii,且呈降序排列(***i<ii>*>*>*>...)

2.从尾部开始寻找第一个大于i的数j,交换i,j位置,由于j是(第一个)大于i的数,交换后保证了序列整体的最小递增性(相当于先确定了递增性的最高位)

3.反转ii以及之后序列:使ii及之后序列递增排列,从而确保了低位的最小递增性

4.若序列已经全部降序排列(即i=first),反转序列,返回false


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 ii = i;  
        --i;  
        if(*i < *ii) {  
            BidirectionalIterator j = lase;  
            while(!(*i < *--j));  
  
            iter_swap(i, j);  
            reverse(ii, last);  
            return true;  
        }  
          
        if(i == first) {  
            reverse(first, last);  //全逆向,即为最小字典序列,如cba变为abc  
            return false;  
        }  
    }  
  
} 


3.应用代码及结果

#include<iostream>
#include<vector>
#include<iterator>
#include<deque>
#include<algorithm>

using namespace std;

int main()
{
	deque<int> d1;
	vector<int> v1;
	int dim1[]={1,2,3};
	v1.assign(dim1,dim1+3);
	cout<<"vector v1 : "<<endl;
	copy(v1.begin(),v1.end(),ostream_iterator<int>(cout,", " ));
	cout<<endl;
	cout<<"deque d1(Original) : "<<endl;
	copy(v1.begin(),v1.end(),back_inserter(d1));
	copy(d1.begin(),d1.end(),ostream_iterator<int>(cout,", " ));
	cout<<endl<<endl;
	
	while(next_permutation(d1.begin(),d1.end()))
	{
		copy(d1.begin(),d1.end(),ostream_iterator<int>(cout,", " ));
		cout<<endl;
	}
	cout<<endl;
	//全降序排列后反转原序列
	copy(d1.begin(),d1.end(),ostream_iterator<int>(cout,", " ));
	cout<<endl;

	getchar();
}



4.小结

stl库中next_permutation算法用来输出序列的全排列比较方便,需注意输入序列(数字或字母)为升序时才能得到全部的排列组合,使用时需要包含头文件<algorithm>,当找到最后序列,即全为降序排列时,返回false,序列全部逆转,变为初始的升序排列。,prev_permutation算法的用法类似,只不过是寻找全排列序列中输入序列之前的序列。

  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章