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算法的用法類似,只不過是尋找全排列序列中輸入序列之前的序列。

  

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