功率集只是给定集的所有子集的集合。
它包括所有子集(空集)。
众所周知,这个集合中有2^N
个元素,其中N是原始集合中元素的数量。
要构建电源设置,可以使用以下内容:
创建一个循环,迭代从0
到2^N-1
的所有整数
继续进行每个整数的二进制表示
每个二进制表示是一组N位(对于较小的数字,添加前导零)。
如果特定集合成员包括在当前子集中,则每个位对应。
import java.util.NoSuchElementException;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;
public class PowerSet<E> implements Iterator<Set<E>>, Iterable<Set<E>> {
private final E[] ary;
private final int subsets;
private int i;
public PowerSet(Set<E> set) {
ary = (E[])set.toArray();
subsets = (int)Math.pow(2, ary.length) - 1;
}
public Iterator<Set<E>> iterator() {
return this;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Cannot remove()!");
}
@Override
public boolean hasNext() {
return i++ < subsets;
}
@Override
public Set<E> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Set<E> subset = new TreeSet<E>();
BitSet bitSet = BitSet.valueOf(new long[] { i });
if (bitSet.cardinality() == 0) {
return subset;
}
for (int e = bitSet.nextSetBit(0); e != -1; e = bitSet.nextSetBit(e + 1)) {
subset.add(ary[e]);
}
return subset;
}
// Unit Test
public static void main(String[] args) {
Set<Integer> numbers = new TreeSet<Integer>();
for (int i = 1; i < 4; i++) {
numbers.add(i);
}
PowerSet<Integer> pSet = new PowerSet<Integer>(numbers);
for (Set<Integer> subset : pSet) {
System.out.println(subset);
}
}
}
我得到的输出是:
[2]
[3]
[2, 3]
java.util.NoSuchElementException
at PowerSet.next(PowerSet.java:47)
at PowerSet.next(PowerSet.java:20)
at PowerSet.main(PowerSet.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)
所以,问题是:
答案 0 :(得分:1)
问题出在hasNext
。你在那里i++ < subsets
。会发生的事情是,hasNext
从next()
调用一次,在迭代期间再次调用for (Set<Integer> subset : pSet)
,每次i
增加2
。你可以看到这个
for (Set<Integer> subset : pSet) {
}
实际上相当于:
Iterator<PowerSet> it = pSet.iterator();
while (it.hasNext()) {
Set<Integer> subset = it.next();
}
另请注意
if (bitSet.cardinality() == 0) {
return subset;
}
是多余的。请尝试改为:
@Override
public boolean hasNext() {
return i <= subsets;
}
@Override
public Set<E> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Set<E> subset = new TreeSet<E>();
BitSet bitSet = BitSet.valueOf(new long[] { i });
for (int e = bitSet.nextSetBit(0); e != -1; e = bitSet.nextSetBit(e + 1)) {
subset.add(ary[e]);
}
i++;
return subset;
}