#include <iostream> #include <algorithm> #include <iterator> using namespace std; /* * use STL next_permutation */ void permutation0(int *arr, int p, int q) { do { copy(arr, arr+q, ostream_iterator<int>(cout, " ")); cout<<endl; }while(next_permutation(arr, arr+q)); } /* * use recursion */ void permutation1(int *arr, int p, int q) { if(p == q) { copy(arr, arr+q, ostream_iterator<int>(cout, " ")); cout<<endl; return; } for(int i=p; i<q; i++) { swap(arr[i], arr[p]); permutation1(arr, p+1, q); swap(arr[i], arr[p]); } } /* * implement next_permutation version 1 in STL * 在i+1->n-1中,找到第一个比i大的数,交换,然后将i+1以后的数按从小到大排序, * 这样保证了无跳跃情况出现 */ bool nextPermutation1(int *arr, int n) { int i; for(i=n-2; i>=0; i--) { for(int j=n-1; j>i; j--) { if(arr[j] > arr[i]) { swap(arr[i], arr[j]); sort(arr+i+1, arr+n); return true; } } } if(0 > i) { return false; } return true; } /* * implement next_permutation version 2 in STL * 分析发现,我们逆向寻找第一个i满足arr[i]<arr[i+1],此时有arr[i]<arr[i+1]>arr[i+2]>arr[i+3]>... * 则arr[i]是需要被交换的元素,而从i+1->n-1是逆序的,无法寻找到下一个排列 * 此时,可用一次循环寻找i,若未找到,全排列完毕,返回 * 进一步分析发现,若在arr中逆向找到第一个下标 j 满足arr[i]<arr[j], * 则有...>arr[j-1]>arr[j]>arr[i]>arr[j+1]>..., 因此arr从i+1->n-1在交换前后都是逆序的 * 此时只需逆转i+1->n-1部分,而无须进行排序,进而保证交换后无跳跃情况 */ bool nextPermutation2(int *arr, int n) { int i; for(i=n-2; i>=0; i--) { if(arr[i] < arr[i+1]) { break; } } if(0 > i) { return false; } for(int j=n-1; j>i; j--) { if(arr[j] > arr[i]) { swap(arr[i], arr[j]); reverse(arr+i+1, arr+n); return true; } } return true; } /* * implement permutation by ourselves */ void permutation2(int *arr, int p, int q) { do { copy(arr, arr+q, ostream_iterator<int>(cout, " ")); cout<<endl; }while(nextPermutation2(arr, q)); } int main() { int a[4] = {1,2,3,4}; permutation2(a, 0, 4); return 0; }