1. 程式人生 > >C++ 標準庫 permutation

C++ 標準庫 permutation

首先,permutation指的是對元素的重排,比如a , b , c 三個元素的所有的重排為    abc, acb, bac,bca,cab,cba 總共 3!  = 6 中情況,但是如何聲稱這六種情況呢,C++標準庫定義了函式 next_permutation,來生成一組元素的所有的全排列。

首先,瞭解該函式的宣告以及實現:

函式宣告為: [摘自 www.cplusplus.com]

std::next_permutation

default (1)
template <class BidirectionalIterator>
  bool next_permutation (BidirectionalIterator first,
                         BidirectionalIterator last);
custom (2)
template <class BidirectionalIterator, class Compare>
  bool next_permutation (BidirectionalIterator first,
                         BidirectionalIterator last, Compare comp);
此兩者在C++的標準庫中被實現為模板的形式。

引數說明:

first last   其中的迭代器  first 和 last 用來表示元素的範圍 [ first, last ) 不對稱邊界。

再來就是該迭代器的型別為雙向迭代器,那麼也就是說 隨機迭代器和雙向迭代器可以作為該函式的引數傳入。

Compare comp   是用來比較的函式,也就是說用來決定生成的重排的順序函式,預設使用的是opeartor<符號,當然你自己也可以定義自己的比較函式,作為函式指標傳入,或者是定義仿函式,傳入函式物件,

返回值:

如果在該comp函式下,下一個重拍序列存在,則返回true,走則返回false,也就是說這一次的重拍序列已經是最後一個重排序列了。

比如,如果採用的是operator<作為比較函式的話,那麼 {1,2,3}的最後一個重排就是321,第一個重排就是123,在321之後再呼叫next_premutation,返回false,但是該函式會將原來的陣列排列為 1,2,3。

副作用:

該函式會修改傳入的元素順序。

#include 
#include 

int main()
{
    int A[] = {1,3,2};
    do{
        std::cout << A[0] << " " << A[1] << " " << A[2] << std::endl;
    }while(std::next_permutation(A,A+3));
    return 0;
}
執行結果為:


可以看出,該函式會自動在當前的元素的順序基礎上,生成後續的排列。也就是說,如果要生成所有的permutation的話,那麼需要先將元素排序。

 OK!!用法已經詳解了,接下來便是要將該函式的真面目示人了。

template <class _BidirectionalIter>
bool next_permutation(_BidirectionalIter __first, _BidirectionalIter __last) {
  __STL_REQUIRES(_BidirectionalIter, _BidirectionalIterator);
  __STL_REQUIRES(typename iterator_traits<_BidirectionalIter>::value_type,
                 _LessThanComparable);
  if (__first == __last) //如果傳入引數為空的話,
    return false;
  _BidirectionalIter __i = __first; 
  ++__i;
  if (__i == __last) //如果只有一個元素
    return false;
  __i = __last;
  --__i;

  for(;;) {
    _BidirectionalIter __ii = __i;
    --__i;
    if (*__i < *__ii) {
      _BidirectionalIter __j = __last;
      while (!(*__i < *--__j))
        {}
      iter_swap(__i, __j);
      reverse(__ii, __last);
      return true;
    }
    if (__i == __first) {
      reverse(__first, __last);
      return false;
    }
  }
}

以上為STL中的版本,該函式實現原理如下:

在當前的序列中,從尾端出發往前找到一對相鄰的元素  a[ i ] 與 a[ j ] ,使得 a[ i ]  < a[ j ], (此處預設採用less函式物件),然後再從尾端出發找到一個字元  a[ k ] ,使得 a[ i ]  < a[ k ], 此時交換 a[ k ] 與 a[ i ], 並且將a[ j --- end) 之間的所有元素逆序即可。程式碼實現為:

template<class bidirectional_iterator>
bool permutation(bidirectional_iterator first, bidirectional_iterator last)
{
    if(first == last) return false; //如果沒有元素

    if(first + 1 == last) return false; //如果只有一個元素

    bidirectional_iterator j = last;
    --j;

    while(1)
    {
        bidirectional_iterator i = j;
        --i;
        //find a[i] < a[j] and they are adjacent
        if(*i < *j)
        {
            bidirectional_iterator k = last;
            while(!(*i < *--k)){}
            std::iter_swap(i,k); //或者是  swap(*i, *k);
            std::reverse(j,last);
            return true;
        }
        --j;
        //no such a[i] < a[i+1] pair found
        if( j == first)
        {
            //restore the first of the permutation
            std::reverse(first, last);
            return false;
        }
    }
}

上述程式碼中的swap函式必須是iter_swap函式,利用swap只是交換了迭代器的指標,並未實際改變元素的位。也可以使用swap(*i, *k);

關於該函式的comp物件的實際形式,接著會有一篇關於函式指標以及函式物件的博文,詳細講解。

2014 5.18 更新版本

看到網上的一篇文章的求解全排列:

如果只需要直接返回所有的全排列的話,那麼很簡單,依次交換字串中的相鄰的字元即可。

如下圖:


相關推薦

C++ 標準 permutation

首先,permutation指的是對元素的重排,比如a , b , c 三個元素的所有的重排為    abc, acb, bac,bca,cab,cba 總共 3!  = 6 中情況,但是如何聲稱這六種情況呢,C++標準庫定義了函式 next_permutation,來

C標準pow函數精度問題。

一般來說 nbsp any pre 4.5 logs urn padding signed #include <stdio.h> int main () { int temp,i; double a=2.4568; unsigned char b[5]

C標準stdlib.h概況

庫函數 字符常量 函數返回 表示 size_t 字節 max size 字符集 庫變量 size_t 這是無符號整數類型,它是 sizeof 關鍵字的結果 wchar_t 這是一個寬字符常量大小的整數類型。 div_t 這是 div 函數返回的結構 ldiv_t 這

C++標準算法

fill acc bsp c++ count nbsp size count() style 一、只讀算法 1. find() 2. count() 3. accumulate 4. equal 二、寫入算法 1. fill 2. fill_nC++標準庫算法

C++標準

補充 ref idt 例如 cat bool 操縱程序 nta 取余 C++標準庫 C++標準庫和標準模版庫在線資料查詢網址: http://en.cppreference.com/w/ 或者 http://www.cplusplus.com/ C+

C 標準 - string.h之strncpy使用

填充 reat 函數 clas != count imu serve uno strncpy 把 src 所指向的字符串復制到 dest,最多復制 n 個字符。當 src 的長度小於 n 時,dest 的剩余部分將用空字節填充。 char *strncpy(char

C 標準 - string.h之strcat使用

www. href 產生 rmi put for turned med main strcat Appends a copy of the source string to the destination string. The terminating null cha

C 標準 - string.h之strlen使用

rac ati oob [] mine eat including 定義 mina strlen Returns the length of the C string str. The length of a C string is determined by the

C 標準 - string.h之memcpy使用

uno over character copies www. zhang 別名 .com val memcpy Copy block of memory Copies the values of num bytes from the location pointed t

C 標準IO緩沖區和內核緩沖區的區別

io緩沖區 lose 信息 同一文件 upload 同步 load IT 覆蓋 1.C標準庫的I/O緩沖區 UNIX的傳統 是Everything is a file,鍵盤、顯示器、串口、磁盤等設備在/dev 目錄下都有一個特殊的設備文件與之對應,這些設

c++標準裏的sort()排序函數

C++ STL Sort()函數是c++一種排序方法之一,學會了這種方法也打消我學習c++以來使用的冒泡排序和選擇排序所帶來的執行效率不高的問題!因為它使用的排序方法是類似於快排的方法,時間復雜度為n*log2(n),執行效率較高!一,sort()排序函數的使用方法I)Sort函數包含在頭文件為#in

C++標準vector類型的使用和操作總結

種類 style 開始 spa log string string類 gpo targe   vector是一種類型對象的集合,它是一種順序容器,容器中的所有對象必須都是同一種類型。vector的對象是可以動態生長的,這說明它在初始化時可以不用指定大小,而是再使用時根據元素

c++標準函數棧和隊列

regex nbsp 頭文件 word pretty tac reg 包含 AS 使用標準庫的棧和隊列時, 應包含先關頭文件. 在棧中應包含頭文件: #include< stack > 定義: stack< int > s; s.empty();

什麽是 CC ++ 標準

lec 內存占用 串處理 函數 背景 成員 流程 出版 contain 簡要介紹編寫C/C ++應用程序的領域,標準庫的作用以及它是如何在各種操作系統中實現的。我已經接觸C++一段時間了,一開始就讓我感到疑惑的是其內部結構:我所使用的內核函數和類從何而來? 誰發明了它們?

初探 C++ 標準(二十六)

C++ 標準庫 cout cin 操作符重載 今天我們來看下 C++ 中的標準庫,這幾天我們一直學習的是 C++ 中的一大難點,操作符重載。那麽我們想想操作符左移 << 可以重載嗎?操作符 << 的原生語義是按位左移,如:1 << 2,則

C++標準(三)之STL算法

out section 區間 and include pla sort 不同 重復元素 算法頭文件: #include<algorithm> #include<numeric> 算法簡介:STL算法采用覆蓋模式而非安插模式,所以調用者必須保證有足夠

C++標準(四)之String

條件 val first operator ins iter substr() oid tof String 常見操作 bool empty() const size_type size() const size_type length() const size_type

C++標準(六)之traits技術

對象的引用 pointer 處的 fde ifd partial clas .... n) traits技術 原理:利用template的參數推導機制獲取傳入的參數型別。 template<typename T> struct Iter { typede

C++標準(七)之iterator

控制 ins opera access 指向 begin 任務 multiset fse iterator iterator模式:提供一種方法,使之能依次訪問容器內的各個元素,而又不暴露該聚合物內部的表述方式。 STL的中心思想是將算法與數據結構分離,彼此獨立設計,最後在用

C++標準——STL之空間配置器

但是 chunk 內容 既然 部分 如何 標識 stl源碼 strong 聲明:源碼同《STL源碼剖析》(侯捷) STL:   C++標準的模板庫,通用性高。   常見的數據結構封裝。   提供常用的通用算法。 STL六大組件:   容器 算法 叠