广度优先搜索,A *搜索图表?

时间:2009-10-20 20:23:08

标签: graph a-star breadth-first-search

我理解如何在树形结构中使用广度优先搜索和A *,但是如下图所示,它将如何实现?换句话说,搜索将如何遍历图表? S是开始状态

Graph Here

6 个答案:

答案 0 :(得分:3)

它与在树中执行它完全相同。你只需要以某种方式跟踪你已经访问过的节点,这样你就不会进入圈内了。

答案 1 :(得分:2)

基本上,您使用与处理树相同的方式处理图形,除非您需要跟踪已经访问过的节点。这对BFS来说很好。最重要的是,在A *的情况下,考虑一下当你重新访问一个节点但你找到了一个更便宜的路径时你会做什么。

答案 2 :(得分:0)

绘制图形 - 递归搜索每个节点并将您访问过的节点标记为脏。仅在图表不脏时才递归。

如果内存不是问题,请复制图形,而不是标记节点,将其从复制图中删除。

答案 3 :(得分:0)

这是加权图。你想找到最短路径还是只是遍历它? 如果你只是想要遍历,那么它就是:

1) there is only S in the queue
2) we are adding C and A in the queue, only they are reachable from S directly (with one edge) 
3) D, G2 - from C
4) B, E - from A
5) G1 - from D (G2 is already in the queue)
6) there no outgoing edge from G2
7) there's no adjacent nodes of B which aren't already in the queue

所以这里是队列中添加节点的顺序:S,C,A,D,G2,B,E,G1

答案 4 :(得分:0)

我不知道你会发现这有多大帮助,但这里有一个用函数式语言J编写的完整解决方案(可从jsoftware.com免费获得)。

首先,直接从您在图片中显示的图表的表示中工作可能是最简单的。我将其表示为(#nodes)x(#nodes)表,在(i,j)处有一个数字,表示node-i和node-j之间的链接值。此外,沿着对角线,我将数字与每个节点本身相关联。

所以,我按如下方式输入 - 不要过于担心不熟悉的符号,你很快就会看到结果如何:

     grph=: <;.1&>TAB,&.><;._2 ] 0 : 0
    A   B   C   D   E   G1  G2  S
A   2   1           8           2
B       1   1   1       4       2
C       3   1               5   
D               1       5   2   
E                   6   9   7   
G1                      0       
G2                          0   
S   2       3                   5
)

所以,我已经将变量“grph”指定为9x9表,其中第一行和第一列是标签“A” - “E”,“G1”,“G2”和“S”;我已经使用制表符来分隔项目,因此可以根据需要将其剪切并粘贴到电子表格中。

现在,我将检查我的桌子的大小并显示它:

   $grph
9 9
   grph
+---+--+--+--+--+--+---+---+--+
|   | A| B| C| D| E| G1| G2| S|
+---+--+--+--+--+--+---+---+--+
| A | 2| 1|  |  | 8|   |   | 2|
+---+--+--+--+--+--+---+---+--+
| B |  | 1| 1| 1|  | 4 |   | 2|
+---+--+--+--+--+--+---+---+--+
| C |  | 3| 1|  |  |   | 5 |  |
+---+--+--+--+--+--+---+---+--+
| D |  |  |  | 1|  | 5 | 2 |  |
+---+--+--+--+--+--+---+---+--+
| E |  |  |  |  | 6| 9 | 7 |  |
+---+--+--+--+--+--+---+---+--+
| G1|  |  |  |  |  | 0 |   |  |
+---+--+--+--+--+--+---+---+--+
| G2|  |  |  |  |  |   | 0 |  |
+---+--+--+--+--+--+---+---+--+
| S | 2|  | 3|  |  |   |   | 5|
+---+--+--+--+--+--+---+---+--+

它看起来不错,很容易将其与图表的图片进行比较以进行检查。 现在我将删除第一行和第一列,这样我们只剩下数字(作为盒装文字), 并删除任何无关的制表符。

   grn=. TAB-.~&.>}.}."1 grph

您可以看到我将此结果分配给变量“grn”。

接下来,我将用“_”替换任何空单元格 - 表示无穷大 - 然后将文字转换为数字表示形式(将结果重新指定为相同名称“grn”):

   grn=. ".&>(0=#&>grn)}grn,:<'_'

最后,我将最后一列和一行移到开头,因为这是“S”的那一行,它应该是第一列。我还会显示结果以确认它看起来是正确的。

   ]grn=. _1|."1]_1|.grn   NB. "S" goes first.
5 2 _ 3 _ _ _ _
2 2 1 _ _ 8 _ _
2 _ 1 1 1 _ 4 _
_ _ 3 1 _ _ _ 5
_ _ _ _ 1 _ 5 2
_ _ _ _ _ 6 9 7
_ _ _ _ _ _ 0 _
_ _ _ _ _ _ _ 0

所以,现在我有一个简单的8x8数字表来表示图形,这是一个简单的事情来遍历它。

这是一个简单的J函数,称为“traverseGraph”,用于读取此表,遍历它所代表的图形,并返回两个结果:所访问节点的索引(从0开始的原点),以及点的值和访问顺序的边缘。

traverseGraph=: 3 : 0
   pts=. ,_-.~,ix{y [ nxt=. ix=. ,0
   while. 0~:#nxt=. ~.ix-.~;([:I._~:])&.><"1 nxt{y do.
        ix=. ix,nxt [ pts=. pts,_-.~,nxt{y
   end.
   ix;pts
)

我们首先初始化三个变量:索引列表“ix”(为零,因为我们想要从表的第0行开始),变量“nxt”指向下一组节点(最初与起始节点相同),以及点值列表“pts”(从输入表的第0行开始,内部称为“y”,删除所有无限值。)

在“while”中。循环,我们继续,只要有超过零“nxt”值,因为从表中拉出当前行并删除我们已经访问过的任何节点(在“ix”中)。在循环内部,我们将下一组索引累积到“nxt”的末尾,将点值累积到“pts”。最后,我们将索引和点值作为(双元素)结果返回。

我们这样运行 - 它默认显示结果:

   traverseGraph grn
+---------------+---------------------------------------------+
|0 1 3 2 5 7 4 6|5 2 3 2 2 1 8 3 1 5 2 1 1 1 4 6 9 7 0 1 5 2 0|
+---------------+---------------------------------------------+

因此,第一个框包含以“0”开头并以“6”结尾的索引。第二个盒装项是按照我们累计它们的顺序的点值向量。我不知道你对这些做了什么,所以我只是展示它们。

我们可以使用索引来显示节点名称,如下所示:

   0 1 3 2 5 7 4 6{(<"0'SABCDE'),'G1';'G2'
+-+-+-+-+-+--+-+--+
|S|A|C|B|E|G2|D|G1|
+-+-+-+-+-+--+-+--+

我不知道你会发现这个有用,但它确实概述了一个解决问题的简单方法。

答案 5 :(得分:0)

您可以阅读我关于广度和深度优先搜索/ A *搜索的系列帖子。它包含C#中的源代码实现。

我使用图形结构来实现代码。

看看我的博文: