使用 STL 在 C++ 中实现 Bentley-Ottmann

Posted

技术标签:

【中文标题】使用 STL 在 C++ 中实现 Bentley-Ottmann【英文标题】:Implementing Bentley-Ottmann in C++ using the STL 【发布时间】:2016-05-08 15:47:43 【问题描述】:

我想使用 STL 元素实现基于此描述的 Bentley-Ottmann 线段交叉算法。 Bentley-Ottmann Wikipedia

我正在苦苦挣扎的是优先队列的实现。描述要求我删除任何交叉点:

如果 p 是线段 s 的左端点,则将 s 插入 T 中。找到 T 中紧接在 s 下方和上方的线段 r 和 t(如果它们存在),并且如果它们的交叉形成了潜在的未来事件事件队列,删除它。如果 s 与 r 或 t 交叉,则将这些交叉点作为潜在的未来事件添加到事件队列中。

似乎不可能使用 STL 优先级队列作为事件队列,因为它的搜索复杂性是线性的,我需要找到并删除 s 的任何交叉点>t。我应该改用一套吗?或者是否可以使用优先队列?

【问题讨论】:

【参考方案1】:

您可以快速删除优先级队列结构,但它们需要大量额外内存。

实际上将 r-t 交叉点留在队列中效率更高。然后,当需要处理事件时,如果它无效(因为 r 和 t 不相邻)或者它已经完成,则忽略它。

为了检测 r-t 何时已经完成,只需确保您的优先级队列按总排序排序,即不要只比较事件的 x 值。当多个事件具有相同的 x 值时,使用所涉及的段的标识符来打破平局。然后,当 r-t 在队列中出现多次时,所有出现的都会一起出现,你可以按顺序将它们全部弹出。

【讨论】:

谢谢 :) 所以如果我说得对的话,实际上只使用一组会更容易,因为它会简单地丢弃重复项?还是效率低下? 不,您仍然需要排序,所以只需使用 STL 优先级队列,并在遇到重复事件时忽略它们。即,不是弹出队列中的第一个事件,而是弹出第一个事件 以及它后面的所有相同事件。您最终可能添加到队列中的额外事件总数少于线段总数,因此将重复项留在队列中并不昂贵。 不是一个集合也能保证正确的顺序吗?我们可以让它按 x 值排序 是的,STL 集可以工作,但优先级队列更快,内存效率更高

以上是关于使用 STL 在 C++ 中实现 Bentley-Ottmann的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中实现通用堆栈

使用 C++ 和 STL 的向量元素乘积

c++之stack使用

如何在 STL 向量中实现 push_back?

C++ STL之stack详解

GLM + STL:运算符 == 缺失