子集生成方法

来源:互联网 发布:皮影客软件 编辑:程序博客网 时间:2024/05/29 19:07

给出一个不含重复元素的集合,求得其子集的各种情况并输出!

 

方法一:增量构造法

             思路是一次选出一个元素放到集合中去,程序如下:

代码:

#include<stdio.h>#define N 100int p[N+2],num[N+2];int cmp(const void *a, const void *b) {return *(int *)a-*(int *)b;}void print_subset(int n, int *p, int cur){    int i,s;    for(i=0;i<cur;i++) {        //printf("%d ",p[i]);printf("%d ",num[p[i]]);    }    if(i==0) printf("空集\n");    else  printf("\n");    if(cur!=0)         s=p[cur-1]+1;//确定当前元素的最小可能的下标else s=0;    for(i=s;i<n;i++) {        p[cur]=i;        print_subset(n,p,cur+1);    }}int main() {    int n,i;    scanf("%d",&n);for(i=0;i<n;i++)scanf("%d",&num[i]);qsort(num,n,sizeof(int),cmp);//这里不排序也可以求得,只是子集不是按照字典序的    print_subset(n,p,0);     system("pause");    return 0;}


 方法二:位向量法

            思路是用一组向量p[i], 如果值为1,则表示了选择了num[i],否则没选。这种方法需要遍历到头之后才能得到一组解,效率低于方法一

代码:

#include<stdio.h>#include<string.h>#include<stdlib.h>#define N 100int p[N+2],num[N+2];int cmp(const void *a, const void *b) {return *(int *)a-*(int *)b;}void print_subset(int n,int cur){    int i,flag;if(cur==n) {for(i=0,flag=0;i<n;i++) {if(p[i]==1) {printf("%d ",num[i]);flag=1;}}if(flag==0) printf("空集\n");else  printf("\n");//确定当前元素的最小可能值return ;}        for(i=0;i<=1;i++) {//p[cur]=1表示num数组的第cur个元素用了,p[cur]=0表示不选,这种方法只能等遍历到头才能输出一组解        p[cur]=i;        print_subset(n,cur+1);    }}int main() {    int n,i;    scanf("%d",&n);for(i=0;i<n;i++)scanf("%d",&num[i]);qsort(num,n,sizeof(int),cmp);//这里不排序也可以求得,只是子集不是按照字典序的    print_subset(n,0);     system("pause");    return 0;}

 

方法三:二进制法,不是很懂。。。

代码:

#include<stdio.h>#include<stdlib.h>#define N 100int p[N+2];void print_subset(int n,int s) {    int i,flag;    for(i=0,flag=0;i<n;i++) {        if(s&(1<<i)) {printf("%d ",p[i]);flag=1;}    }    if(flag==0) printf("空集\n");else printf("\n");} int main() {    int n,i;    scanf("%d",&n);for(i=0;i<n;i++) {scanf("%d",&p[i]);}    for(i=0;i<(1<<n);i++) {        print_subset(n,i);    }    system("pause");return 0;}