使用 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的主要内容,如果未能解决你的问题,请参考以下文章