C++ 将小重叠块合并为较大连续块的有效算法?

C++ 将小重叠块合并为较大连续块的有效算法?,c++,algorithm,performance,C++,Algorithm,Performance,我面临一个相当有趣的问题。我有很多街区。块就是从偏移开始,具有长度和颜色的东西。偏移量和长度是有限的——这些区块存在的空间是N从几十万到几百万的范围。无效块是指偏移量大于N或偏移量与长度之和大于N的任何块。一个块可能有16种不同的颜色(仅其中一种) 可能有数千个街区,而且总是会出现这样的情况: 块X:关闭:100,透镜:50,颜色:蓝色 块Y:关闭:148,透镜:50,颜色:蓝色 block_Z:off:200,len:30,颜色:红色 如您所见,X和Y块可以连接到一个较大的块中,从而导致: b

我面临一个相当有趣的问题。我有很多街区。块就是从偏移开始,具有长度和颜色的东西。偏移量和长度是有限的——这些区块存在的空间是N从几十万到几百万的范围。无效块是指偏移量大于N或偏移量与长度之和大于N的任何块。一个块可能有16种不同的颜色(仅其中一种)

可能有数千个街区,而且总是会出现这样的情况:

块X:关闭:100,透镜:50,颜色:蓝色
块Y:关闭:148,透镜:50,颜色:蓝色
block_Z:off:200,len:30,颜色:红色

如您所见,X和Y块可以连接到一个较大的块中,从而导致:

block_XY:off:100,透镜98,颜色:蓝色
block_Z:off 200,镜头30,颜色:红色

我想创建一个算法,将通过所有的块,并连接那些重叠,并有相同的颜色。实际上,如果块之间的间隙相当小(我可以选择一个常数,大约16个,但可能是任何数字…),那么我还是想连接这些块。请注意,在上面的示例中,只有两个块连接在一起。实际上,可以连接的块序列在大多数情况下要长得多

还有一个有趣的转折,考虑一下:

块A:关闭:100,透镜:200,颜色:蓝色
块B:关闭:200,透镜:200,颜色:蓝色
块C:关闭:300,透镜:150,颜色:红色
block\u D:off:400,len:200,颜色:蓝色
block_E:off:500,len:200,颜色:蓝色

正如你所看到的,我们有一个很好的蓝色块序列,可以合并成一个大的蓝色块。然而,在它的中间也有一个小的红色块。这不应该愚弄算法,正确的结果是:

block\u ABDE:off:100,len:600,颜色:蓝色
块C:关闭:300,透镜:150,颜色:红色

数据存储在std::multimap中,其中键是偏移量,值是包含块的长度和颜色的结构,类似于:
multimap
。请注意,可能存在以相同偏移开始的块。但是,可以保证,如果发生这种情况,从同一偏移开始的块具有不同的颜色和不同的长度


有人能想出一个好主意来有效地解决这个问题吗该算法的目标是减少我们拥有的块数,但不需要将其减少到尽可能小的数量。

我建议如下:

  • 为每种颜色创建一个单独的列表
  • 对于每个特定颜色,计算所有块的开始(偏移)和结束(偏移+长度)
  • 按起始值对每个特定于颜色的列表进行排序
  • 现在,遍历每个列表,合并项目:如果下一个项目的开始小于或等于上一个项目的结束(加上允许的间隙),则删除下一个项目并扩展上一个项目

  • 将块列表分隔为每种颜色的列表,并按块的起始偏移量对所有这些列表进行排序。(实际上,在基于颜色过滤时,您可能需要执行插入排序,或者按偏移量排序,然后按颜色进行稳定排序,并使用数组的分区。)

    一旦你有了每种颜色的列表,你将迭代每一个:从第一个块开始,检查下一个块的偏移量是否足够接近你当前块的末尾,如果是的话,合并它们。然后继续到列表的末尾

    现在,您已经组合了每种颜色的所有块,因此您可以连接列表以获得所有颜色的所有块的最终列表。最昂贵的步骤(渐进)是排序,因此这可能足够有效。使用比数组和链表更高级的数据结构,您可能会想出一些平均速度更快的方法,但在您衡量这种更简单方法的性能之前,这些麻烦是不值得的


    请注意,由于两个块是否可以合并的规则仅取决于一个块的端点和另一个块的起点,而不取决于块的大小,因此任何能够识别任何潜在合并的解决方案都可能会识别所有合并,并且合并的顺序无关紧要(也就是说,合并是一种关联操作)。

    您不必为每种颜色将块拆分为一个列表。您可以按块开始地址对整个列表进行排序,然后通过维护单独的{start,length}在一次过程中对其进行处理每种颜色配对。

    这相当简单,因为对于每种颜色,它就像一个编号范围,例如

    蓝色:100-299200-400500-670671-702

    您将其合并到:

    蓝色:100-400500-702

    只需按范围中的第一个值排序,并查看结束值(实际上是最后一个元素之后的值)。如果该值大于或等于下一个元素的开始值,则它们合并

    在上面的300>200中,它们合并,401<500,它们不合并,671==671,它们合并


    对每种颜色执行相同的操作。

    或者您可以先按颜色排序,然后按偏移量排序。