关于数列的全排列已经另外一篇文章中提到过了,
下面来介绍下数列的组合问题:
例如;序列12345 如果输入m=3,原序列的长度n=5
得到的组合数组是:123 124 125 134 135 145 234 235 245 345
如上得到所有的位数为2的组合方式,从上面的数我们也可以用序号表示:
a[0],a[1],a[2],a[3],a[4],a[5]
得到的组合数a[0],a[1],a[2]可用下标012表示
那么组合数就可以用原来数列的的下标表示即可:
从一开始,得到的组合数列,所有组合数的下标是递增 的,最后一个组合序列的最后一位的下标即为n-1;
我们定义一个数组p[x]=y 取到的第x个元素是数组a中的第y个元素 x代表的是组合序列的中的元素的索引 y代表的是数组a中的元素索引。
#include<stdio.h> #include <stdlib.h> bool zuhe(char a[],int n,int m) { int index,i,*p; p=(int*)malloc(sizeof(int)*m); if(p==NULL) { return false; } index=0;//index代表的是组合串中的元素的索引,即代表组合数中的第几个数 p[index]=0;//取第一个元素,从一个元素开始 while(true) { /*组合数中的某一个位置的元素到达原数组最后一个 原素了,比如15_ 或者125 其中的5 达到数组的最后一个元素*/ if(p[index]>=n) { if(index==0) { //此时组合的第一个数也达到了数组中的最后一个数。退出循环 break; } index--; //此时的组合数列的index位置上的数已经达到数组最后一个数,所以回到前一个位置,将其加1 ps. 135--->14_ p[index]++; } else if(index==m-1)//此时已经组合到最后一个位置,可以输出 { for(i=0;i<m;i++) { printf("%c",a[p[i]]); } printf("\n"); //此时的index已经达到组合数的最后一个位置,exp 134->135 p[index]++; } else //此时index还未达到最后的位置exp 13_--->134 { index++; p[index]=p[index-1]+1; } } }
但是上述办法还是不能解决原数列出现重复元素的问题:还得需要后期的去重处理。
如果将这些求一个数列的排列组合的方法结合起来,就可以解决如下的一个问题
问题:
当给以出一个数列,求出其所有的组合函数,比如abc 输出:a,b,c,ad,ac,bc,abc
只需在上面的基础之上加一个for循环即可:
main()
{
char a[]="12345";
for(int i=1;i<=5;i++)
{
printf("i:%d:\n",i);
zuhe(a,5,i);
}
}