在复杂度方面最好的寻路算法是什么?

时间:2019-01-06 16:40:37

标签: algorithm complexity-theory dfs

我需要在我的一个程序中实现寻路算法。目的是知道路径是否存在。因此,知道路径本身并不重要。

我已经做过一些研究,但我不确定该选哪个。 This帖子一直在告诉DFS或BFS更适合此类程序,但我希望知道确切的情况后再进行确认。我也想知道程序本身的复杂性,但是我想我可以找到这个。不共享就可以了。

这是我正在使用的图形:假设我有一个x * y网格,其中包含路径可以和不能采用的区域。 我想知道是否存在从图的顶部开始并在图的底部结束的现有路径。这是路径为红色的示例:

Example

我相信DFS在复杂性方面是最好的,但是我也不知道确切的实现方式,也不确定确切的实现方式。我不确定在路径可以开始的每个不同点上启动DFS还是更好,或者我是否添加了路径可以用来进行一项测试的区域区域。

谢谢您的帮助!

1 个答案:

答案 0 :(得分:3)

您可以在此处采用多种不同的方法。假设您正在使用的网格的大小与上面显示的大致相同,并且假设您没有一次处理数百万个网格,那么广度优先搜索和深度优先搜索都有可能会同样有效。广度优先搜索的优势在于,它将找到从顶部到底部的最短路径;缺点是,与深度优先搜索相比,它通常需要更多的内存。但是同样,如果您使用的网格数量大约为数百或数千个单元,那么这种内存开销可能不会成为太大的问题。我会说选择最适合您的算法并继续使用它。

关于如何实现从“顶部任何地方”到“底部任何地方”的搜索,您可以通过几种不同的方式来实现。

  1. 如果您使用的是深度优先搜索,则可以从第一行的每个单元格中进行一个深度优先的搜索,然后搜索下一行的路径。 DFS要求您维护一些有关哪些单元已被访问和尚未访问的信息。如果在所有对DFS的调用中都回收了相同的信息,则将确保没有两个调用执行任何重复的工作,因此,生成的解决方案应该非常有效,对于m×n的网格按时间O(mn)运行。

  2. 如果您使用广度优先搜索,则修改非常简单:在搜索开始时,不只是将单个起点排队在队列中,还可以将搜索开始。然后,BFS会自然地探索从顶部行中任何地方开始的所有可能路径。

  3. 可以用不同的方式来考虑这两种想法。假设您的网格是graph,其中每个单元格都是一个节点,边对应于成对的相邻单元格。然后,您可以添加一个新节点,该节点位于网格顶行上方,并连接到顶行中的每个节点。然后,添加一个新节点,该节点位于底行的正下方,并连接到底行的每个节点。现在,如果存在从新的顶部节点到新的底部节点的路径,则意味着存在从顶部行中的某个节点到底部行中的某个节点的路径,因此在此图中进行单个搜索就足以检查路径是否存在。 (有趣的事实:上面对DFS和BFS的两个修改都可以认为是在此新图中进行隐式搜索。)

您可能要考虑的另一种选择是,它比DFS或BFS相当容易实现,并且效率明显低下,并且可以使用disjoint-set forest data structure来确定所连接的东西。该数据结构支持两种查询:

  • 给出两个单元格,标记出有一种方法可以从第一个单元格转到第二个单元格。 (“联盟”)
  • 给定两个单元格,确定它们之间是否存在一条路径,该路径可以是直接路径,也可以通过将多个其他路径链接在一起来形成。 (“查找”)

您可以通过建立一个不相交的森林,将所有相邻单元对联合在一起,然后将顶行中的所有节点结合在一起,并将底行中的所有节点结合起来来实现连接性查询。进行“查找”查询以查看顶部节点中的任何一个是否连接至底部节点中的任何一个,即可解决您的问题。函数α(mn)增长得如此缓慢以至于实际上只有3或4个函数,这将花费时间O(mnα(mn)),因此它的效率与BFS或DFS一样有效。