线性阵列,节点随机链接到阵列中的其他节点,最短路径

时间:2009-02-18 19:01:35

标签: php delphi shortest-path

信息: 我有一个包含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,但了解我正在寻找的是什么[代码也有帮助]。

5 个答案:

答案 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进行后向引用(开始节点)。

然后对于此后列表中的每个元素,直到您到达结尾,执行以下操作:

  1. 如果它在集合中已经跳过它(你已经访问过它)并移动到列表中的下一个项目。
  2. 否则,将其添加到集合中,并将其可以到达的所有节点添加到列表中,并对您正在“查看”到列表末尾的索引进行反向引用。然后转到列表中的下一个索引并重复。
  3. 如果在任何时候到达终点节点(最好是将其添加到列表中 - 而不是在列表中访问它),请追溯​​到对起始节点的反向引用并反转路径。

    示例:

    给定节点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的节点推送到队列中。现在,重复邻居搜索此队列中的所有节点。并继续这样做,直到你得到你的女孩,错误,结束。