【问题标题】:Find all possible path between two nodes in a undirected graph在无向图中找到两个节点之间的所有可能路径
【发布时间】:2011-02-22 04:07:35
【问题描述】:

谁能给我一个 C 代码来查找两个节点之间的所有可能路径? 例如。 如果图有以下边 1-2 1-3 2-3 2-4 3-4

1 到 4 之间的所有路径都是:

1-2-3-4

1-2-4

1-3-4

1-3-2-4

【问题讨论】:

标签: c


【解决方案1】:

深度优先搜索可以完成这项工作。

【讨论】:

  • 并非如此。 DFS 可能会为您提供一些路径,但不是全部。
  • @Keith。想想 n-queen 问题的 dfs 解决方案。
  • 我认为您正在考虑的解决方案(遍历所有可能的方格,如果可能,在此处放置一个皇后,然后递归)不是 DFS。
  • DFS 不会重新访问它已经访问过的节点。如果你这样做(因为你需要为 OP 的问题做),我不会称之为 DFS。维基百科 (en.wikipedia.org/wiki/Depth-first_search) 同意我的看法。不过,我同意你,如果你允许重新访问已完成但不在进行中的节点,你可能会解决 OP 的问题。
  • @Keith:因为维基百科文章的开头说 深度优先搜索 (DFS) 是一种用于遍历或搜索树、树结构或图的算法。一个从根开始(在图形案例中选择某个节点作为根)并在回溯之前尽可能沿着每个分支探索,我不相信这支持您的论文。它明确提到了回溯,这是确保完全覆盖所必需的。
【解决方案2】:

(我假设您不希望路径中有重复节点 - 否则可能的路径数量是无限的。)

你可以放松一下:

while (there is a change) {
  for (v in nodes(G)) {
    for (e in edges(v)) {
      paths_to[v] = paths_to[v] union ((paths_to[e.to] not containing v) append v)
    }
  }
}

结果仍然可以是输入图大小的指数。获取所有路径可能不是您想要做的。

【讨论】:

    【解决方案3】:

    这是解决问题的简单算法。这不是一个最优算法。

    static struct {
      int value1;
      int value2;
      int used;
    } data[] = {
      { 1, 2 },
      { 1, 3 },
      { 2, 3 },
      { 2, 4 },
      { 3, 4 },
    };
    
    enum { DATA_SIZE = sizeof data / sizeof *data };
    
    static int output[DATA_SIZE];
    
    int traverse(int from, int to, int depth) {
      output[depth++] = from;
    
      int i;
      if (from == to) {
        for (i = 0; i < depth; i++) {
          if (i) {
            printf("-");
          }
          printf("%d", output[i]);
        }
        printf("\n");
      } else {
        for (i = 0; i < DATA_SIZE; i++) {
          if (!data[i].used) {
            data[i].used = 1;
    
            if (from == data[i].value1) {
              traverse(data[i].value2, to, depth);
            } else if (from == data[i].value2) {
              traverse(data[i].value1, to, depth);
            }
    
            data[i].used = 0;
          }
        }
      }
    }
    
    int main() {
      traverse(1, 4, 0);
    }
    

    【讨论】:

    • 嗨,bkail,感谢您的程序。但我在检查以下节点时发现了一些困难,太多的周期即将到来。您可以尝试以下边并找到在 1 和 4 之间没有重复节点的路径 {0, 5}, {1 ,4}, {0, 2}, {5 ,4}, {1 ,2}, {4 , 3 }, {3 ,10}, {1, 6 }, {6 ,2 }, {2,3 }, {2, 7 }, {3 ,14 }, {6, 7 }, {7, 8 } , {8, 10 }, {8, 9 }, {8 ,12 }, {8 ,14}, {5 ,11 }, {10 ,11 }, {10 ,13}, {10 ,9 }, { 11 ,14 }, {11 ,12 }, {12 ,13 }, {13 ,14 },
    【解决方案4】:

    递归方法:

    findPaths(path = startNode, goal)
        paths = []
        if the last node in path is goal:
            return path
        for each node n connected to the last node in path:
            if n is not already on the path:
                paths.append(findPaths(path.append(node), goal))
        return paths //may still be []
    

    【讨论】:

      【解决方案5】:

      为时已晚,不是 C 代码,但可能对其他人有所帮助。这个算法展示了我如何在 java 中实现它。

      findPath(start) 
          Childs = getDirectChildsOf(start)
          foreach child in Childs
              tempRoute;
              tempRoute.add(start)
              if (child == end)
                  return tempRoute.add(child) 
              else 
                  tempRoute.add(findPath(child))
                  if (tempRoute.last() == end)
                      return tempRoute;
      

      这里的tempRoute 可能是一个维护节点列表的Route 类。可以将单个node 和其他route 添加到tempRoute。 它也找不到所有可能的路径。为此,您必须为每个节点维护一个访问标志。

      【讨论】:

        猜你喜欢
        • 2012-03-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-18
        • 2021-09-19
        • 2015-02-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多