zoukankan      html  css  js  c++  java
  • 子集生成

    子集生成

    给定一个集合,枚举所有可能的子集。在这里的集合是{0,1,2...n-1}

    1.增量构造法

    感觉紫书上这段代码不是很好理解,画了一个图来辅助理解。这里的集合是{0,1,2...n-1},也可以看作是下标的集合,对任意集合,只要能输出它的下标的子集,也就能够输出该集合的子集。
    这段代码还使用了定序的技巧,即所有元素是从小到大排列,在输出{1,2}后就不会输出{2,1}了,细细体会。
    增量法的解答树共有(2^n)个结点,因为每个可能的A都对应一个结点,n元集合就有(2^n)个子集。

    代码:

    void print_subset(int n, int* A, int cur){
    	for(int i = 0; i < cur; ++i) printf("%d", A[i]); //打印当前集合
    	printf("
    ");
    	int s = cur ? A[cur-1] :  0;          //确定当前元素的最小可能值
    	for(int i = s; i < n; ++i){
    		A[cur] = s;
    		print_subset(n, A, cur+1);         //递归构造子集
    	}
    }
    
    2.位向量法

    构造一个位向量B[i],当B[i]=1,i在子集A中。通过位向量法的解答树能够理解,这里的解答树结点的结点总数为2047个,比增量构造法多,因为包含了部分解。

    解答树的结点,我的理解是每次递归调用自身,就产生一个结点。

    代码:

    void print_subset(int n, int *B, int cur){
    	if(cur == n){
    		for(int i = 0; i < n; ++i)
    			if(B[i]) printf("%d ", i);
    		printf("
    ");
    		return;
    	}
    	B[cur] = 1;
    	print_subset(n, B, cur+1);
    	B[cur] = 0;
    	print_subset(n, B, cur+1);
    }
    

    3.位运算法

    代码:

    void print_subset(int n, int i){
    	for(int s = 0; s < n; ++s){
    		if(i & (1<<s)) printf("%d ", s);
    	printf("
    ");
    	}
    }
    
    for(int i = 0; i < (1<<n); ++i)
    	print_subset(n, i);
    
  • 相关阅读:
    为什么MySQL数据库索引选择使用B+树?
    nginx负载均衡策略
    视频笔记
    mysql show full processlist 分析问题
    Git利用命令行提交代码步骤
    zend studio远程自动上传代码并执行
    CentOS7 通过YUM安装MySQL5.7 linux
    PHP的按位运算符是什么意思
    git 分支操作
    php 技术知识点汇总
  • 原文地址:https://www.cnblogs.com/patrolli/p/11480134.html
Copyright © 2011-2022 走看看