[C/C++] [递归] 寻找n个整数的所有组合

输入一组数据(集合),将该组数据的所有子集按照顺序输出

例如:输入【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个整数的所有组合。

  • 23
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值