参考了 http://www.acmerblog.com/combinations-of-r-elements-6059.html
#include <stdio.h>
#include <algorithm>
#include <cstring>
void combine(int arr[], int data[], int start, int end,int idx,int r){
// has found r elements
if(idx == r){
for (int i = 0; i < r; ++i) {
printf("%d ",data[i]);
}
puts("");
return ;
}
// the left elements less than r -idx, return
if(start + r - idx > end) return;
data[idx] = arr[start];
//add the arr[start] to collection
combine(arr,data,start+1,end,idx+1,r);
//skip the arr[start] to collection
combine(arr,data,start+1,end,idx,r);
}
void permute(int arr[],int start, int end, int idx, int r){
if(idx == r){
for (int i = 0; i < r; ++i) {
printf("%d ",arr[i]);
}
puts("");
return ;
}
if (start + r -idx > end) return;
for (int i = start; i < end ; ++i) {
std::swap(arr[start],arr[i]);
permute(arr,start+1,end,idx+1,r);
std::swap(arr[start],arr[i]);
}
}
bool permute_advanced(int arr[], int start, int end){ //[start, end-1]
int i = end-1;
//find to incremental adjacent tuple from backward,
// ( arr[idx-1],arr[idx] ) is the tuple
while(i>start && arr[i-1] >=arr[i]) i--; // '=' is important!
//if without '=' ,
//there will be infinit loop
//when there is duplicant elements
if(i == start){
//reverse the arr;
int j = end - 1;
while(i<j) std::swap(arr[i++],arr[j--]);
return false;
}
// the index of the min element which is larger than arr[i-1]
int k = i;
for (int j = i; j <=end-1; ++j)
if (arr[j] > arr[i-1] && arr[j] <=arr[k]) { // '=' is important
k = j; // to ensure we find the farest element
} // when we swap(arr[i-1],arr[k])
// we get arr[i...end-1], a non-incremental array
//swap
std::swap(arr[i-1],arr[k]);
// backward from i to end-1
int j = end -1;
while(i<j) std::swap(arr[i++],arr[j--]);
return true;
}
bool identical_array(int a[], int b[], int n){
for (int i = 0; i < n; ++i) {
if (a[i] != b[i]) return false;
}
return true;
}
int main(){
int arr[] = {2,2,2,2,2,2,1};
int n = sizeof(arr)/sizeof(arr[0]) ;
int * arr_copy = new int [n];
for (int i = 0; i < n; ++i) {
arr_copy[i] = arr[i];
}
for (int i = 0; i <=n; ++i) {
int* data = new int[i];
combine(arr,data,0,n,0,i);
free(data);
}
for (int i = 0; i <=n; ++i) {
permute(arr,0,n,0,i);
}
//if you don't want deplicant sequence, you use below code
do{
for (int i = 0; i < n; ++i) {
printf("%d ",arr_copy[i]);
}
puts("");
//}while(permute_advanced(arr_copy,0,n));
}while(std::next_permutation(arr_copy,arr_copy+n));
//if the array is not incremental sorted, we have to do it again.
do{
if(identical_array(arr,arr_copy,n)) break;
for (int i = 0; i < n; ++i) {
printf("%d ",arr_copy[i]);
}
puts("");
}while(std::next_permutation(arr_copy,arr_copy+n));
}