信息: 我有一个包含100个节点的数组,[0 .. 99]。每个节点可以有任意数量的链接节点:
eg1,0链接到5,10,15,20。 eg2,1链接到30,40,50。 eg3等。
所有100个节点至少有一个链接节点,节点不知道谁链接到它们。
问题: 如果提供START和END,我如何找到最短的链接路径。
例如。 START = 5,END = 80,链接路径(示例):[5] - > 10-> 24-> 36-> [80]?
我正在使用Pascal和/或PHP,但了解我正在寻找的是什么[代码也有帮助]。
答案 0 :(得分:2)
大量阅读/算法: Shortest path problem。你实际上只是拥有相同权重的所有边缘(“链接”,就像你所说的那样)。
答案 1 :(得分:1)
从Start节点开始执行广度优先遍历,并在找到结束节点后立即退出。
答案 2 :(得分:1)
这有周期吗?即是DAG吗?
如果没有周期:
List<Node> GetShortestPath(Node startNode, Node endNode)
{
//If this is the node you are looking for...
if (startNode.ReferenceEquals(endNode))
{
//return a list with just the end node
List<Nodes> result = new List<Nodes>();
result.Add(endNode);
return result;
}
List<Node> bestPath = null;
foreach(Node child in startNode.Children)
{
//get the shortest path from this child
List<Node> childPath = GetShortestPath(child, endNode);
if (childPath != null &&
( bestPath == null || childPath.Count < bestPath.Count))
{
bestPath = childPath;
}
}
bestPath.Insert(0, startNode);
return bestPath;
}
[编辑:为周期添加了一个示例] 如果可以有周期:
List<Node> GetShortestPath(Node startNode, Node endNode)
{
List<Node> nodesToExclude = new List<Node>();
return GetShortestPath(startNode, endNOde, nodesToExclude);
}
List<Node> GetShortestPath(Node startNode, Node endNode, List<Node> nodesToExclude)
{
nodesToExclude.Add(startNode);
List<Node> bestPath = null;
//If this is end node...
if (startNode.ReferenceEquals(endNode))
{
//return a list with just the child node
List<Nodes> result = new List<Nodes>();
result.Add(endNode);
return result;
}
foreach(Node child in startNode.Children)
{
if (!nodesToExclude.Contains(child))
{
//get the shortest path from this child
List<Node> childPath = GetShortestPath(child, endNode);
if (childPath != null &&
( bestPath == null || childPath.Count < bestPath.Count))
{
bestPath = childPath;
}
}
}
nodesToExclude.Remove(startNode);
bestPath.Insert(0, child);
return bestPath;
}
答案 3 :(得分:1)
两种结构:一组和一个列表。
在集合中,您存储已访问过的节点。这可以防止您进行以下循环。
列表包含以下对象:(1)一个节点,以及(2)指向找到它的节点的指针。
从起始节点开始,将其添加到集合中,使用空后引用将其添加到列表中,然后将其可以到达的所有节点添加到列表中,并对列表中的索引0进行后向引用(开始节点)。
然后对于此后列表中的每个元素,直到您到达结尾,执行以下操作:
如果在任何时候到达终点节点(最好是将其添加到列表中 - 而不是在列表中访问它),请追溯到对起始节点的反向引用并反转路径。
示例:
给定节点0到3,其中
node0 - &gt;节点1
node0 - &gt;节点2
node1 - &gt;节点2
node2 - &gt;节点3
node0是START,node3是END
SET = {}
LIST = []
第1步 - 添加START:
SET = {node0}
LIST = [[node0,null]]
步骤2 - 在列表的索引0处 - 添加可到达的节点:
SET = {node0,node1,node2}
LIST = [ [node0,null] ,[node1,0],[node2,0]]
步骤3 - 在LIST的索引1处 - 添加可到达的节点:
node2已经在SET中。跳过将可到达的节点添加到LIST
SET = {node0,node1,node2}
LIST = [[node0,null], [node1,0] ,[node2,0]]
步骤4 - 在LIST的索引2处 - 添加可到达的节点:
SET = {node0,node1,node2,node3}
LIST = [[node0,null],[node1,0], [node2,0] ,[node3,2]]
第5步 - 到达END,现在回溯:
在LIST中插入的END节点(node3)具有对列表中索引2的后引用,即node2。它有一个对列表中索引0的后引用,即node0(START)。反转这个,你得到node0的最短路径 - &gt; node2 - &gt;节点3。
答案 4 :(得分:0)
这是树/图还是森林?如果它是森林,则可能不会始终定义路径。如果这是树/图,请尝试使用广度优先搜索。
以这种方式思考:比如说,你正在隐形任务中找到你附近可爱的小鸡。你从自己的家开始,把它标记为START。你接下来会去敲你最近的邻居吧?所以,我们会这样做 - 将所有连接到start的节点推送到队列中。现在,重复邻居搜索此队列中的所有节点。并继续这样做,直到你得到你的女孩,错误,结束。