子集树与排列树

一、子集树
当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间称为子集树
现需打印序列(长度为n)的全部子集,将问题抽象转化为一棵二叉树.
一个序列的所有子集为2^n,即可看成具有2^n个叶节点的满二叉树,总结点个数为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);
    }

}

打印结果:
这里写图片描述

  • 11
    点赞
  • 57
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值