求全排列的话有两种方法:
方法一:利用递归,将一个排列看成是以一个数开头+另外一个子排列, 例如数组list[n]的全排列,以list[i]表示以元素list[i]开头的一个排列,所以所有的排列数为list[0]+list[1]+list[2].......list[n-1], 以list[i]为首元素的排列可以看成是list[i] 为首,加上另外n-1个元素排列的排列。这里每次以list[i]为首时候,可以将list[i]和list[0]交换元素,然后求自序列list[1]----list[n-1]的排列,就可以递归下去
/*
* recursion
*/
void full_rank_recurisive(int *list,int n,int num)
{
if(num == n)
{
print_list(list,list+n);
putchar('\n');
return;
}
int i ;
for(i = num;i<n;i++)
{
swap(&list[i],&list[num]);
full_rank_recurisive(list,n,num+1);
swap(&list[i],&list[num]);
}
}
方法二:不采用递归的方法,首先将数组看成是一个递增的,这与我们手写排列是一个习惯,每次从右边找到第一个元素,这个元素比他右边的元素小,他右边的元素都是单调递减的,然后再从右边重新扫描,找到第一个比他大的元素,交换元素值,然后再将他右边的元素从小到大排列,如此循环,知道找不到那个元素为止
void full_rank(int *p_start,int *p_end)//inorder from little to big
{
print_list(p_start,p_end);
putchar('\n');
while(1)
{
int *ptr = p_end - 2;
for(;ptr !=p_start - 1; ptr--)
{
if(*ptr < *(ptr+1))
break;
}
if(ptr == p_start - 1)
break;
int *p2 = p_end - 1;
for(;p2 != ptr;p2--)
{
if(*p2 > *ptr)
break;
}
swap(ptr,p2);
qsort(ptr+1,p_end - ptr-1,sizeof(p2[0]),cmp);
print_list(p_start,p_end);
putchar('\n');
}
}
关于组合,使用递归或者穷举,每个数要么被选,要没不被选,就这两种选择
void DFS(int *src,int *dest,int n,int m, int k,int index)
{
if(k == m || index == n)
{
print_list(dest,dest+m);
putchar('\n');
return;
}
if(n - index == m - k)
{
for(;index<n;)
dest[k++] = src[index++];
print_list(dest,dest+m);
putchar('\n');
}
else{
dest[k] = src[index];
DFS(src,dest,n,m,k+1,index+1);
DFS(src,dest,n,m,k,index+1);
}
}