来自多个位域的互斥连续范围

时间:2011-02-02 05:01:41

标签: c++ range bit-fields

(这不是CS课程的家庭作业,即使它看起来像一个)

我使用位域来表示0到22之间的范围。作为输入,我有几个不同的范围,例如(顺序无关紧要)。我为.使用0,为X使用1以提高可读性。

.....XXXXX..............
..XXXX..................
.....XXXXXXXXXXXXXXX....
........XXXXXXX.........
XXXXXXXXXXXXXXXXXXXXXXXX

位域范围的数量通常低于10,但可能会高达100.从该输入,我想计算互斥的连续范围,如下所示:

XX......................
..XXX...................
.....X..................
......XX................
........XX..............
..........XXXXX.........
...............XXXXX....
....................XXXX

(同样,输出顺序无关紧要,它们只需要相互排斥和连续,即它们不能有空洞。.....XXX.......XXXXX....必须分成两个单独的范围。 / p>

我尝试了几种算法,但所有这些算法都变得相当复杂和不优雅。有什么能帮助我的方法是检测.....XXX.......XXXXX....有一个洞和一种确定洞中某个位的索引的方法。

编辑:位域范围代表地图上的缩放级别。它们旨在用于输出Mapnik的XML样式表(由OpenStreetMap使用的平铺渲染系统)。

2 个答案:

答案 0 :(得分:0)

我会考虑你的子问题,至少......

  

什么能帮助我极大地发现这一点   .....XXX.......XXXXX....有一个洞和一种确定索引的方法   洞中的一个位。

在位掩码中查找最低和最高位(“1”)位非常漂亮 解决问题;例如,请参阅glibc中的ffs(3),或参阅 例如http://en.wikipedia.org/wiki/Bit_array#Find_first_one

给定位图的第一个和最后一个索引,将其称为ij, 您可以计算具有ij设置的所有位的位图 使用M = ((1 << i) - 1) & (~((1 << j) - 1))(对任何人道歉) 断接一个-错误)。

然后,您可以通过比较它来测试原始位图是否有孔 M。如果它不匹配,您可以使用输入xor M来查找 洞和重复。

答案 1 :(得分:0)

我假设您在评论中提到的解决方案是这样的:

从左侧或右侧开始(因此索引= 0),并扫描设置了哪些位(最多100次操作)。设置x的名称。还设置变量block = 0。

在index = 1时,重复并存储以设置y。如果x XOR y = 0,则两者都是相同的集合,因此转到index = 2。如果x XOR y = z!= 0,那么范围[block,index]是连续的。现在设置x = y,block = index,然后继续。

如果您有100个长度为22的位数组,则需要大约2200次操作。

这是一个最佳解决方案,因为无法进一步减少操作 - 在每个阶段,如果另一组与您的设置不匹配,您的范围会被破坏,因此要检查范围是否已损坏,您必须检查所有100位。