大部分平衡双分区的排列
Permutation for mostly balanced bipartitions
我正在研究一种树搜索算法,其中我使用通过位集表示的元素的二分法,即位集 1000101
表示二分法 {0,2,6} {1,3,4,5}
.
目前,我只是通过递增一个位集来遍历所有二分,即遍历集合 {0,1,2,3}
的所有二分,我从 0001
(含)到 1000
(独占)
由于我的算法有时允许我 'fail fast' 当我找到合适的二分法时,我想重新排序它们以便我首先查看更平衡的二分法。
因此,我想问问是否有人知道从 1 到 2^k 的数字排列,其中 min(#set bits, #unset bits) 或多或少只会减少,这可以仍然可以高效计算.
由于这是一种启发式方法,我不是在寻找准确的结果,只是想稍微加快我的算法速度。
Rory 的评论让我走上了正确的方向:
如果我们从 bitset 中的固定数量开始,我们可以简单地使用一些 bit-twiddling hack 遍历所有这些。
从0...01...1
开始,先是k/2
,然后是k/2 - 1
,k/2 - 2
等等。
对于每个起始值,使用 Gosper's Hack 迭代位集的所有可能排列,直到我们到达位集的边界。
一个简单的实现可能看起来像这样(对于 k <= 63
)
for (int i = k / 2; i > 0; --i) {
// start with 0 ... 0 1 ... 1 (i times)
unsigned int v = (1 << i) - 1;
// first bitset that doesn't represent a valid bipartition
unsigned int end = 1 << k;
// without this, we would count some bipartitions twice for k even
if (k % 2 == 0 && i == k / 2) end >>= 1;
while(v < end) {
// do something with v...
// iterate to the lexicographically next permutation
unsigned int t = v | (v - 1);
v = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
}
}
我正在研究一种树搜索算法,其中我使用通过位集表示的元素的二分法,即位集 1000101
表示二分法 {0,2,6} {1,3,4,5}
.
目前,我只是通过递增一个位集来遍历所有二分,即遍历集合 {0,1,2,3}
的所有二分,我从 0001
(含)到 1000
(独占)
由于我的算法有时允许我 'fail fast' 当我找到合适的二分法时,我想重新排序它们以便我首先查看更平衡的二分法。
因此,我想问问是否有人知道从 1 到 2^k 的数字排列,其中 min(#set bits, #unset bits) 或多或少只会减少,这可以仍然可以高效计算.
由于这是一种启发式方法,我不是在寻找准确的结果,只是想稍微加快我的算法速度。
Rory 的评论让我走上了正确的方向:
如果我们从 bitset 中的固定数量开始,我们可以简单地使用一些 bit-twiddling hack 遍历所有这些。
从
0...01...1
开始,先是k/2
,然后是k/2 - 1
,k/2 - 2
等等。对于每个起始值,使用 Gosper's Hack 迭代位集的所有可能排列,直到我们到达位集的边界。
一个简单的实现可能看起来像这样(对于 k <= 63
)
for (int i = k / 2; i > 0; --i) {
// start with 0 ... 0 1 ... 1 (i times)
unsigned int v = (1 << i) - 1;
// first bitset that doesn't represent a valid bipartition
unsigned int end = 1 << k;
// without this, we would count some bipartitions twice for k even
if (k % 2 == 0 && i == k / 2) end >>= 1;
while(v < end) {
// do something with v...
// iterate to the lexicographically next permutation
unsigned int t = v | (v - 1);
v = (t + 1) | (((~t & -~t) - 1) >> (__builtin_ctz(v) + 1));
}
}