含有 n 个元素的子集树问题

一、子集树
当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间称为子集树
现需打印序列(长度为n)的全部子集,将问题抽象转化为一棵二叉树.
一个序列的所有子集为2n,即可看成具有2n个叶节点的满二叉树,总结点个数为2^(n+1)-1.
需定义额外数组保存当前分支的打印信息(左分支置1,右分支置0)
每遍历完一条分支,打印当前分支序列
子集树
如上图:用数组arr={1,2,3}举例
brr[] 子集
111 ——> 123
110 ——-> 12
101 ——-> 13
100 ——-> 1
011 ——-> 23
010 ——> 2
001 ——> 3
000 ——> 空集
代码实现:

/**
* 求子集的程序
* @param ar
* @param br
* @param i
* @param length
*/
private static void func1(int[] ar, int[] br, int i, int length) {
if(i == length){
//br[] 111 110 101 100 011 010 001 000
//子集 123 12 13 1 23 2 3 空集
for(int k=0; k<length; ++k){
if(br[k] == 1){
System.out.print(ar[k] + " ");
}
}
System.out.println();
} else {
br[i] = 1; //标1
func1(ar, br, i+1, length); //产生分支
br[i] = 0; //标0
func1(ar, br, i+1, length); //产生分支
}
}

二、排序树
当所给问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。排列树通常有n!个叶子节点。因此遍历排列树需要O(n!)的计算时间。

如上图:用arr[]={1,2,3}举例
(1)开始,数组有三个元素,相当于生成了一个3叉树(n个元素就是n叉树)每一个分叉确定一个排列组合中第一个元素的一种情况
(2)接着往下递归,确定第二个元素,{}中的元素进行交换,与自己和后面每个元素交换。
注意:每一次分叉比前一次减少一个分支(因为已经确定了一个位置的元素)
(3)直到{ }中只有一个元素,所有排列组合都列举完毕
代码实现:

public class Test2 {
/**
* 求ar数列的全排列
* @param ar
* @param k
* @param length
*/
private static void func2(int[] ar, int k, int length) {
if(k == length){
for(int i=0; i<length; ++i){
System.out.print(ar[i] + " ");
}
System.out.println();
} else {
for(int i=k; i<length; ++i){
swap(ar, k, i); //k和后面元素交换
func2(ar, k+1, length); //数组个数就是叉数 生成结点
swap(ar, k, i); //交换回去
}
}
}

/**
 * 交换数组的k和i号位元素的值
 * @param ar
 * @param k
 * @param i
 */
private static void swap(int[] ar, int k, int i) {
    int tmp = ar[k];
    ar[k] = ar[i];
    ar[i] = tmp;
}
 public static void main(String[] args) {
    int[] ar = {1,2,3};
    func2(ar,0,ar.length);
}

}
1、子集树解空间的最大叶节点数目就是n个元素的最多的子集个数,很明显n个元素的每一个元素都有两种选择是否位于子集中,故最多的子集个数为2^n;
2、那么子集树解空间的最多节点数为多少?答案很简单: 20+21+22+…+2n=2^(n+1)-1;
3、n个元素的排序树的最多叶子节点个数是n个元素的全排列,即n!


作者:XD_fybdw
来源:CSDN
原文:https://blog.csdn.net/XD_fybdw/article/details/80870560

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值