The STL provides two algorithms for calculating the permutations and combinations of relationships, namely Next_permutation and prev_permutation. First we must understand what is the "next " permutation, what is the "previous" permutation combination. consider a sequence of three characters {a,b,c}.
This sequence has six possible permutation combinations: ABC,ACB,BAC,BCA,CAB,CBA. These permutations are sorted according to the Less-than operator in dictionary order (lexicographical) . That is, ABC is ranked first because each element is smaller than the element that follows it. The ACB is the second permutation, because it is a new combination that is fixed after a (the smallest element in the sequence ).
Similarly, the permutations of a fixed B (minor element in a sequence) are arranged in a sequence preceded by a set of rows that are fixed to C . Take BAC and BCA for example, BAC before BCA, because order AC is less than sequence ca. in the face of BCA, we can say that the previous permutation is a bac, and then a permutation is a cab. The sequence ABC does not have a "previous " permutation combination, and the CBA does not have a "latter" permutation.
Next_permutation () takes the next permutation of the sequence indicated by [First,last] and returns False if there is no next permutation, otherwise true. There are two versions of this algorithm. Version one uses the Less-than operator provided by the element type to determine the next permutation combination, and version two is determined by the faux function comp.
Algorithm idea:
1. First from the end of the beginning to look forward to two adjacent elements, so that the first element is *i, the second element is *ii, and satisfies *i<*ii.
2. After finding such a group of adjacent elements, then from the end of the forward test, to find the first element greater than *i, so that the *j, the i,j element Swap (swap).
3. Sort all the elements after the II (reverse) backwards.
For example, assuming that there is a sequence {0,1,2,3,4}, the above algorithm is applied to get the "next" permutation in one step . In the picture, only the two adjacent elements that conform to "one element is *i, the second element is *ii, and satisfy *i<*ii " are not shown in the search for proper J, swap, and reversal operations.
Here is the implementation details for version one. Version two is quite similar and is not listed.
1TEMPLATE<CALSS bidrectionaliterator>2 BOOLnext_permutation (Bidrectionaliterator first,bidrectionaliterator last)3 {4 if(first = = Lase)return false;/*Empty Interval*/5Bidrectionaliterator i =First ;6++i;7 if(i = = last)return false;/*only one element*/8i = last;/*I point to the tail end*/ 9--i;Ten for(;;) One { ABidrectionaliterator II =i; ---i; - /*Lock A group of (two) adjacent elements above*/ the if(*i < *II)/*if the previous element is less than the next element*/ - { -Bidrectionaliterator j = Last;/*make J point to the tail end*/ - while(! (*i < *--j));/*look forward from the tail until it encounters a larger element than the *i.*/ +Iter_swap (I,J);/*Exchange I,j*/ -Reverse (ii,last);/*rearrange all elements after II in reverse order*/ + return true; A } at if(i = = first)/*To the front.*/ - { -Reverse (first,last);/*rearrange all reverse order*/ - return false; - } - } in}
Simple Application
The full arrangement of the output sequence {1,2,3,4} dictionary order.
[Code Implementation]
1#include <iostream>2#include <algorithm>3 using namespacestd;4 intMain ()5 {6 intans[4]={1,2,3,4};7Sort (ans,ans+4);/*This sort can be used because {1,2,3,4} is already sequenced .*/8 Do /*Note that this step, if it is a while loop, requires a pre-output*/9 {Ten for(intI=0;i<4;++i) Onecout<<ans[i]<<" "; Acout<<Endl; -} while(Next_permutation (ans,ans+4)); - return 0; the}
Expand
1. Can I calculate the nth permutation of the set {1, 2, ..., m} directly?
Example: If the set of 7 numbers is {1, 2, 3, 4, 5, 6, 7}, the first n=1654 is required.
(1654/6!) Rounding 2, determining the 1th bit is 3 (counting from 0), the remaining 6 numbers {1, 2, 4, 5, 6, 7}, the 1654th 6!=214 sequence;
(214/5!) Rounding is 1, the 2nd digit is 2, the remaining 5 numbers are {1, 4, 5, 6, 7}, and the No. 214 5!=94 sequence is determined;
(94/4!) Take the whole 3, determine the 3rd bit is 6, the remaining 4 number {1, 4, 5, 7}, the 94th 4!=22 sequence;
(22/3!) Rounding 3, determine the 4th bit is 7, the remaining 3 number {1, 4, 5}, the 22nd 3!=4 sequence;
(4/2!) 2, determine the 5th is 5, the remaining 2 number {1, 4}; Due to 4 2!=0, 6th and 7th digits are <1 4>;
All permutations are therefore: 3267514.
[Code Implementation]
1#include <iostream>2#include <algorithm>3 using namespacestd;4 intMain ()5 {6 intans[7]={1,2,3,4,5,6,7};7Sort (ans,ans+7);/*ditto can not use sort*/8 intn=0; 9 Do //Note that this step, if it is a while loop, requires a pre-outputTen { One if(n = =1654) A { - for(intI=0;i<7;++i) -cout<<Ans[i]; thecout<<Endl; - Break; - } -n++; +} while(Next_permutation (ans,ans+7)); - return 0; +}
2. Given an arrangement, how do you figure out which is the first permutation?
Contrary to the derivation process of the previous question. For example 3267514:
The 6-bit full arrangement is 6!,3 {1, 2, 3, 4, 5, 6, 7} in the 2nd element (counting from 0), so 2*720=1440;
The 5!,2 is the 1th element in {1, 2, 4, 5, 6, 7}, so 1*5!=120;
The 4!,6 is the 3rd element of {1, 4, 5, 6, 7} in the full arrangement of the second 4 bits, so 3*4!=72;
The 3!,7 is the 3rd element in {1, 4, 5, 7}, so 3*3!=18;
The 2!,5 is the 2nd element of {1, 4, 5} in the full arrangement of the second 2 bits, so 2*2!=4;
The last 2 bits are added sequentially, so count 0, sum: 1440+120+72+18+4=1654
This code implementation, you can use an array A to save 3267514, and then the while Call Next_permutation (), with n count, each time with the array a comparison, equal to output n;
Next_permutation (full permutation algorithm)