[家庭作业]
我们必须使用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);
}
}
答案 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。