查找集的功率集

时间:2013-08-27 13:03:08

标签: java c++ algorithm set

[家庭作业]

我们必须使用Java或C ++找到给定集的幂集。该组将以任何大小的数组的形式被接受,我需要显示该组的幂集的元素。请注意,唯一使用的概念是数组,循环和函数(递归和迭代)。

我需要有人指出我可以应用的逻辑方向。 请帮忙。

PS:集合A的幂集是集合A的所有子集的集合 例如。 A = {a,b,c}     权力集A = {{},{a},{b},{c},{a,b},{b,c},{a,c},{a,b,c}}


编辑:

非常感谢“wy”和“MrSmith42”!我使用他们给出的逻辑编写了我的程序。现在我正在尝试优化它。请注意,我是Java的新手,因为它的新颖性而发现它有点不舒服。

这是我的代码:

import java.util.Scanner;

public class PowerSet {

    //Function to increment binary string...

    static String incr_bin (String binary){
        char bin[] = new char[100];
        int size_bin, i;
        size_bin = binary.length();
        bin = binary.toCharArray(); 
        bin[size_bin-1]++;
        for(i=size_bin-1; i>=0; i--){
            if (i != 0){
                if(bin[i] > '1'){
                    bin[i]='0';
                    bin[i-1]++;
                }
            }
        }
        if (bin[0]>'1'){
            for(i=0;i<size_bin;i++){
                bin[i]='0';
            }
        }
        binary = new String (bin);
        return binary;
    }



    public static void main(String[] args) {

        //Declarations

        Scanner in = new Scanner (System.in);
        int a[] = new int [100];
        int size_a, i, count=0;

        String binary;

        //Input

        System.out.println("Enter the number of elements in A : ");
        size_a = in.nextInt();
        char bin[] = new char [size_a];
        System.out.println("Enter the elements in A : ");
        for(i=0; i<size_a; i++){
            a[i] = in.nextInt();
            bin[i] = '0';
        }
        binary = new String(bin);

        //Calculating and Setting up subsets
        System.out.println("MEMBERS OF POWER SET :");
        do{
            System.out.print("\n{.");
            count = 0;
            binary = incr_bin(binary);
            bin = binary.toCharArray();
            for(i=0; i<size_a; i++){
                if (bin[i] == '0') count++;
                if (bin[i] == '1') System.out.print(a[i] + "  ");
            }
            System.out.println("}");
        }while(count!=size_a);      
    }
}

4 个答案:

答案 0 :(得分:9)

您可以将电源组的每个元素映射到二进制数,其位数与集合的大小相同。

e.g。

     A = { a, b, c} 
     binary number  => resulting subset
     000            => {     }  // no 'a',  no 'b', no 'c'
     001            => {    c}
     010            => {  b  }
     011            => {  b,c}
     100            => {a    }
     101            => {a,  c}
     110            => {a,b  }
     111            => {a,b,c}

答案 1 :(得分:5)

要输出功率集,“14.5生成子集”中有三种方法,Alogrithm设计手册,我尝试了所有这些方法只有数组,循环和函数。但是没有代码。这里有关于它们的简短段落:

  

1. 词典顺序 - 词典顺序表示排序顺序,而且是   通常是生成组合对象的最自然的方式。该   字典顺序中的{1,2,3}的八个子集是{},{1},{1,   2},{1,2,3},{1,3},{2},{2,3}和{3}。但令人惊讶的是   难以按字典顺序生成子集。 除非你有   这样做的一个令人信服的理由,不要打扰。

     

2. 格雷码 - 一个特别有趣且有用的子集序列是最小变化顺序,其中相邻子集的不同之处在于   恰好插入或删除一个元素。这样的排序,叫做   格雷码。以格雷码顺序生成子集可以非常快,   因为有一个很好的递归结构。构造格雷码   n - 1个元素G n-1 反转a> G n-1 的第二个副本并添加n到   此副本中的每个子集。然后将它们连接在一起以创建G n 。   此外,由于子集之间只有一个元素发生变化,因此无穷无尽   基于格雷码的搜索算法非常有效。

     

3. 二进制计数 - 子集生成问题的最简单方法基于以下观察:任何子集S'由   S的项目在S'。我们可以用二进制字符串表示S'   其中,比特i是第1个,而第i个元素是S'。这个   定义长度为2 n 二进制字符串之间的双射   n和n个项目的2个 n 子集。对于n = 3,二进制计数   按以下顺序生成子集:{},{3},{2},{2,3},{1},   {1,3},{1,2},{1,2,3}。这个二进制表示是关键   解决所有子集生成问题。生成所有子集   顺序,只需从0到2 n-1 计数。对于每个整数,   连续掩盖每个位并组成精确的子集   对应1位的项目。生成下一个或上一个   子集,将整数递增或递减1.取消子集   实际上是掩蔽过程,而排名构造二进制   1的数字对应于S中的项目,然后将其转换   二进制数到整数。

如果你想要一个简单的,只需二进制计数就足够了,它可以是重复实现,如回溯或特定的。如果你已经完成并想要更多的挑战,你可以编写一个格雷码。您可以在其Wiki页面here上了解如何生成格雷码。

答案 2 :(得分:0)

这是java中的实现。这使用了使用位的上述逻辑。

/**
 * Prints all subsets of a list
 * @param list
 */
public static void printSubsets(List<Integer> list) {
    int max = (int)Math.pow(2, list.size());

    for (int i = 0; i < max; i++) {
        // Convert int to bitset
        BitSet bs = getConvertedBitSet(i, list.size());

        // Use bitset to print the subset
        printSubset(bs, list);
    }
}

/**
 * Helper function for {@link org.vikastaneja.companies.Expedia#printSubsets(java.util.List)}<br/>
 * This function prints the subsets for the bits that are set in bitset
 * @param bs
 * @param list
 */
private static void printSubset(BitSet bs, List<Integer> list) {
    if (list == null) {
        throw new NullPointerException("Set is empty");
    }

    System.out.print("{ ");
    for (int i = 0; i < list.size();i++) {
        if (bs.get(i)) {
            System.out.print(list.get(i) + " ");
        }
    }

    System.out.print("}");

    System.out.println();
}

/**
 * Helper function for {@link org.vikastaneja.companies.Expedia#printSubsets(java.util.List)}<br/>
 * This function converts an integer to the bitset
 * @param value
 * @param size
 * @return
 */
private static BitSet getConvertedBitSet(int value, int size) {
    BitSet bits = new BitSet(size);
    bits.set(0, size - 1, false);
    int index = 0;
    while (value != 0) {
        if (value % 2 != 0) {
            bits.set(index);
        }
        ++index;
        value = value >>> 1;
    }
    return bits;
}

答案 3 :(得分:0)

使用增量/减量进行二进制计数是可以的,直到您的通用集包含的元素数量超过最大整数类型具有的位数为止。但是,继承规则非常简单。给定子集S_k表示为位向量,您将生成S_ {k + 1},如下所示:

for i in 0..len(s):
  if s[i]:
    s[i] = 0
  else:
    s[i] = 1
    break

从[000]开始,很容易看到它会生成[100],[010],[110],[001],... [111]。要生成所有它们,将以上内容循环包装,并跟踪子集的基数,在将位设置为1或0时加或减1。最后一个子集的基数为n。