求集的幂集
Finding Power set of a Set
[作业分配]
我们必须使用Java或C++来找到给定集合的幂集。该集将以任何大小的数组形式接受,我需要显示该集的幂集元素。请注意,唯一要使用的概念是数组、循环和函数(递归和迭代)。
我需要有人为我指明正确的方向,告诉我可以应用的逻辑。请帮忙。
PS:集合a的幂集是集合a的所有子集的集合AA的幂集={{},{A},}b},{c},〔A,b}〕,{b,c}、{A,c}}、{A,b,c}}
编辑:
非常感谢"wy"answers"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);
}
}
您可以将幂集的每个元素映射到一个二进制数,其位数与集的大小相同。
例如
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}
要输出功率集,在"14.5生成子集";,Alogithm设计手册,我已经尝试过所有这些,只有数组、循环和函数。但不会有代码。以下是关于它们的简短段落:
1.词典顺序–词典顺序表示排序顺序,是通常是生成组合对象的最自然的方式。这个{1,2,3}的八个子集按字典顺序是{},{1},{1,2} ,{1,2,3},{1,2},{2},{2,3}和{3}。但令人惊讶的是难以按字典顺序生成子集除非你这是一个令人信服的理由,不用麻烦
2.格雷码–一个特别有趣和有用的子集序列是最小变化顺序,其中相邻子集的差异为插入或删除恰好一个元素。这样的命令,称为a格雷码。以格雷码顺序生成子集可能非常快,因为有一个很好的递归构造。构造格雷码n−1元素的Gn−1反转a>Gn−1的第二个副本,并将n添加到此副本中的每个子集。然后将它们连接在一起以创建Gn。此外,由于子集之间只有一个元素发生变化,因此穷举基于格雷码的搜索算法可能是非常有效的
3.二进制计数–子集生成问题的最简单方法基于以下观察结果:任何子集S'由该S的项在S’中。我们可以用二进制字符串表示S'其中比特i是1iff,S的第i个元素在S’中。这定义长度为2n的二进制字符串之间的双射n、 以及n个项目的2n子集。对于n=3,二进制计数按以下顺序生成子集:{}、{3}、{2}、{2,3}、{1},{1,3}、{1,2}和{1,2,3}。这种二进制表示是解决所有子集生成问题。在中生成所有子集顺序,简单地从0计数到2n-1。对于每个整数,依次屏蔽每个位,并精确地组成对应于1个比特的项目。生成下一个或上一个子集,将整数递增或递减一。取消子集的排名实际上是掩蔽过程,而排序构造二进制带有1的数字对应于s中的项目,然后将其转换二进制数到整数。
如果你想要一个简单的,只要二进制计数就足够了,它可以是递归实现,比如回溯或特定的实现。如果你已经完成了,并且想要更多的挑战,你可以编写一个格雷码。您可以在这里学习如何在其wiki页面上生成格雷码。
下面是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;
}
使用递增/递减的二进制计数是可以的,直到通用集的元素数超过最大整数类型的位数。然而,继承的规则很简单。给定子集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。
- 没有找到相关文章