voidrecursive_permute(intA[],inti,intn){if(i==n-1){for(intj=0;j<n;j++)cout<<A[j]<<" ";cout<<endl;return;}for(intj=i;j<n;j++){swap(A[i],A[j]);// choose A[j] as the ith elementrecursive_permute(A,i+1,n);swap(A[i],A[j]);// reset to enter next for}}
voidrecursive_permute2(intA[],inti,intn){if(i==n-1){for(intj=0;j<n;j++)cout<<A[j]<<" ";cout<<endl;return;}for(intj=i;j<n;j++){intk;for(k=i;k<j;k++)if(A[k]==A[j])break;// A[j] already usedif(k<j)continue;swap(A[i],A[j]);// choose A[j] as the ith elementrecursive_permute2(A,i+1,n);swap(A[i],A[j]);// reset to enter next for}}
boolnext_permute(intA[],intn){inti,j;// step .1if(n<2)returnfalse;for(i=n-2;i>=0;i--){if(A[i]<A[i+1])break;}if(i<0)returnfalse;// A[0] is maximum, no next permute for it// step .2for(j=n-1;j>i;j--){if(A[j]>A[i])break;}// step .3swap(A[i],A[j]);// step .4while(++i<--n){swap(A[i],A[n]);}returntrue;}
/** * @brief Permute range into the next @a dictionary ordering. * @ingroup sorting_algorithms * @param first Start of range. * @param last End of range. * @return False if wrapped to first permutation, true otherwise. * * Treats all permutations of the range as a set of @a dictionary sorted * sequences. Permutes the current sequence into the next one of this set. * Returns true if there are more sequences to generate. If the sequence * is the largest of the set, the smallest is generated and false returned.*/template<typename_BidirectionalIterator>boolnext_permutation(_BidirectionalIterator__first,_BidirectionalIterator__last){// concept requirements__glibcxx_function_requires(_BidirectionalIteratorConcept<_BidirectionalIterator>)__glibcxx_function_requires(_LessThanComparableConcept<typenameiterator_traits<_BidirectionalIterator>::value_type>)__glibcxx_requires_valid_range(__first,__last);if(__first==__last)// 容器中没有元素,没有 next permutereturnfalse;_BidirectionalIterator__i=__first;++__i;if(__i==__last)// 容器中只有一个元素,同没有returnfalse;__i=__last;--__i;// 将 __i 指向最后一个元素for(;;){_BidirectionalIterator__ii=__i;--__i;if(*__i<*__ii){// step .1, 这里的 __i 就相当于上面step 1中的i_BidirectionalIterator__j=__last;while(!(*__i<*--__j)){// step .2, 这里的 __j 就相当上面 step 2中的j}std::iter_swap(__i,__j);// step .3 交换std::reverse(__ii,__last);// step .4 逆置returntrue;}if(__i==__first){// 直到 __i = __first 还是没有 *__i < *__ii ,说明序列是递减排列的std::reverse(__first,__last);// 本应该没有下一个排列,但这里将字典序中第一个排列作为最后一个排列的 next permutereturnfalse;// 这里返回 false 而不是 true}}}
可以看到,其实 STL 的 next permute 的实现跟我们的非递归算法是一致的。但这里有两个问题:一是,这里看似有二重循环(在 for 中套 while ),但实际上复杂度是 n+n =》 O(n) 的(可以为什么要写成这种二重循环的形式捏?不解);二是,我们可以看到在 for 循环中,对 __ii 这个变量进行了多次声明,为什么不将其声明放在 for 外面捏?(虽然待排列的元素数 n 不会很大,但这样多次声明一个迭代器变量,虽不会占用过多内存,但在声明时调用构造函数和析构函数也是有一定的时间开销的吧,虽然相对于求全排列的复杂度 O(n*n!) 几乎可以忽略不计)