求子集

从网上搜集到了几个方法,整理如下:

 

方法一
#include <stdio.h>
#define MAX_N 5

int g_arr[MAX_N] = {0};
__int64 g_cnt = 0;

void Recur(int* arr, int arr_size, int req_cnt)
{
	if (req_cnt > 0){
	//数据没有选够,从剩下的数据中继续选
	//先选中最小的
	arr[0] = 1;
	//然后从剩下的arr_size - 1个数据中选req_cnt-1个数据
	Recur(arr+1, arr_size - 1, req_cnt-1);
	//回溯一下,跳过刚才选的那个最小数的情况
	arr[0] = 0;
		if ((arr_size - 1) >= (req_cnt )){
			Recur(arr+1, arr_size - 1, req_cnt);
		}
	}else{
		//找到一组完整数据
		++g_cnt;
		//输出组合
		int i;
		for(i=0; i<MAX_N; i++){
			if (g_arr[i] == 1){
				printf("%d\t", i);
			}
		}
		printf("\n");
	}
}

int main(int argc, char *argv[])
{
	int i;
	for(i=1; i<=MAX_N; i++)
	Recur(g_arr, MAX_N, i);
	printf("total group = %I64u\n", g_cnt);
	system("PAUSE"); 
	return 0;
}


方法二
#include <stdio.h>
#include <string.h>
int a[16]={0};
unsigned long c[16]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
int b[16]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
int huanerjinzhi(long d){
	int i=0;
	int count=1;int k=d;
	int *p;p=a;
	unsigned long *q;q=c;
	memset(a,0,sizeof(int)*16);
	if(!k) {return 0;}
	else {while(k&=(k-1)){count++;}}
	while(d){
		if(d&(*q)){*p=1;d&=~(*q);p++;q++;}
		else{*p=0;p++;q++;}
	}
	return count;
}
void jisuan(long n)
{
	long i, j, t;
	long r;
	long k=(1<<n);
	for(i=0;i<k;i++){
		t=huanerjinzhi(i);
		printf("{");
		for(r=1,j=0;r<=t;j++)
		if(a[j]==1){
			if(r!=t)printf("%d,",b[j]);
			else printf("%d",b[j]);r++;}
		printf("}\n");
	}
}

int main(int argc, char *argv[])
{
	int n;
	printf("input a number:\n");
	scanf("%d", &n); 
	jisuan(n);
	system("PAUSE"); 
	return 0;
}


方法三

#include <stdio.h> 
//k是开始字符的位置,n是数组的长度,l是子集的位数 
void subArray(int A[], int k,int l, int n); 
//初始化整个子集数组 
void initArray(int n); 
//用于输出子集的数组 
int priArray[4]; 
void printArray(int n); 
int counter = 0; 

int main() 
{ 
int i; 
int array[4] = {1, 2 , 3, 4}; 
//0是所有数组的子集 
printf("0\n"); 
counter += 1; 
for (i = 0; i < 4; i++) 
{ 
initArray(4); 
//递归算法需要保证从第一个元素开始的所有的元素都被遍历到 
priArray[0] = array[i]; 
counter += 1; 
printArray(1); 
subArray(array, i+1, 2, 4); 
} 
printf("\nThe SubArray is %d\n", counter); 
getchar(); 
return 0; 
} 



void subArray(int A[], int k, int l, int n) 
{ 
int i; 
if (k == n-1) 
{ 
//n是整个数组的长度,k是整个子集的上一位字符,当k == n-1时,意味着已经是最后一个了。 
priArray[l-1] = A[k]; 
counter += 1; 
printArray(l); 
} 
else 
{ 
for ( i= k; i <= n-1; ++i) 
{ 
priArray[l-1] = A[i]; 
counter += 1; 
printArray(l); 
subArray(A, i+1, l+1,n); 
} 
} 

} 



void printArray(int n) 
{ 
int i; 
for (i = 0; i < n; i++) 
{ 
printf("%d ", priArray[i]); 
} 
printf("\n"); 
} 

void initArray(int n) 
{ 
for (int i = 0; i<= n-1 ; i++) { 
priArray[i] = 0; 
} 
} 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值