输入一组数据(集合),将该组数据的所有子集按照顺序输出
例如:输入【1,2,3】
输出:
、
输入【1,2,3,4】
输出:
即先输出第一个元素包含的所有情况,再依次输出第2,3,4个...
然后在每一种情况中,按照包含第2,3...个元素的情况输出,同时在每一种情况中按照上述顺序输出。
int main() {
cs = 0;
int n;
scanf("%d", &n);
int a[n+1] = {0};
for (int k = 0; k < n; k++) {
scanf("%d", &a[k]);
}
int data[n];
for (int j = 0; j < n; j++) { //输出以第j个元素为头节点排序的所有情况
paixu(a, n, n - j, 0, data, j);
}
return 0;
}
在主函数中,我们设计了一个循环,每一次循环都会输出以第j个元素开头的所有情况,也可以理解为每循环一次,就去掉一个元素
为此,我们设计了一个输出函数和一个排序函数
首先让我们来看输出函数
void shuchu(int data[], int len) { //输出子串
printf("-->");
for (int i = 0; i < len; i++) {
printf(" %d", data[i]);
}
printf("\n");
}
即在每一种输出情况之后都用换行符进行分隔
接着让我们来看最重要的排序函数部分
int cs = 0; //遍历的次数
void paixu(int a[], int n, int len, int index, int data[], int i) {
if (index == len) { //运行到尾节点时输出
shuchu(data, len);
cs++;
return;
}
if (cs > pow(2, n) - 1){ //遍历次数超过子集的数目时退出
return;
}
if (i >= n){ //当前节点到达或者超过数组长度时退出
return;
}
data[index] = a[i]; //把原数组中的值赋值给data数组
paixu(a, n, len, index + 1, data, i + 1);
paixu(a, n, len - 1, index, data, i + 1);
}
其中需要重点理解的就是paixu(a, n, b, index + 1, data, i + 1); 和paixu(a, n, b - 1, index, data, i + 1);这两个递归式的含义了。
首先解释一下:a[]是输入的数组,n为原数组的长度,len为输出的子集的长度,index为当前节点,data[]为子集数组,i为头节点
我们首先会运行paixu(a, n, b, index + 1, data, i + 1),一直递归直至index=len,例如输入【1,2,3】,会递归3次,输出【1,2,3】
接着回到第二次递归中,paixu(a, n, b - 1, index, data, i + 1)会产生一个输出,此时len = len - 1,data中的元素为【1,2】,满足条件,会输出【1,2】
再回到第一次的递归中,调用paixu(a, n, b - 1, index, data, i + 1),在下一次递归中又会首先运行paixu(a, n, b, index + 1, data, i + 1),而此时i=2,会输出【1,3】,接着调用paixu(a, n, b - 1, index, data, i + 1),此时index = len ,输出【1】
每一次循环都重复如上步骤,最终就会输出n个整数的所有组合。