C#算法搜索两个顶点之间的所有路径

时间:2015-04-10 22:11:07

标签: c# algorithm graph nodes depth-first-search

最近给出了一个在C#中实现权重的有向图的任务。

我是3/4,但我必须使用测试数据并根据该数据返回答案。

我有图表工作,我能够在2个节点之间添加成本,并使用深度优先搜索返回2个节点之间的所有路径。

令我感到困惑的是,其中一个问题如下:找到从节点“C”到“C”的路由数量,成本低于30。

给出的答案是

CDC, 
CBEC, 
CEBCDC, 
CDEBC, 
CEBCEBC, 
CEBCEBCEBC  **7 in total**
These are the input graph details 
"A to B: 5",
"B to C: 4", 
"C to D: 8", 
"D to C: 8", 
"D to E: 6",
"A to D: 5" 
"C to E: 2", 
"E to B: 3", 
"A to E: 7"

我可以

CDC,
CEBC,
CDEBC

使用深度优先搜索,但我不知道其他4个来自哪里,或者为什么你会考虑已经回到目的地节点并继续的路线。

我使用了错误的算法吗?这是我正在尝试的:

public void depthSearch(GraphDeclare<string> graph, LinkedList<DirectedGraphNode<string>> Visited)
    {
        string endNode = "C";
        LinkedList<DirectedGraphNode<string>> nodes = getNeighboursAdjecentNodes(graph, Visited.Last());
        //examine the adjecent nodes
        foreach (DirectedGraphNode<string> node in nodes)
        {

            Boolean contains = Visited.Any(x => x.Value == node.Value);

            if (contains == true)
            {
                // Console.WriteLine("Hello");
                // printPath(Visited);
                continue;
            }
            if (node.Value == endNode)
            {
                Visited.AddLast(node);
                printPath(Visited);
                Visited.RemoveLast();
                break;
            }
        }

        foreach (DirectedGraphNode<string> node in nodes)
        {

            Boolean contain = Visited.Any(x => x.Value == node.Value);

            if (contain == true || node.Value == endNode)
            {
                continue;
            }
            Visited.AddLast(node);
            depthSearch(graph, Visited);
            Visited.RemoveLast();
        }

    }

    private void printPath(LinkedList<DirectedGraphNode<string>> visited)
    {
        StringBuilder cb = new StringBuilder();
        foreach (DirectedGraphNode<string> node in visited)
        {
            cb.AppendLine(node.Value + " ");

        }
        Console.WriteLine(cb.ToString());
    }


    private LinkedList<DirectedGraphNode<string>> getNeighboursAdjecentNodes(GraphDeclare<string> graph, DirectedGraphNode<string> n)
    {
        LinkedList<DirectedGraphNode<string>> neighbours = new LinkedList<DirectedGraphNode<string>>();

        foreach (DirectedGraphNode<string> edge in graph.nodeSet)
        {

            if (edge.Value.Equals(n.Value))
            {
                foreach (DirectedGraphNode<string> neighbour in edge.NeighbourNodes)
                {
                    neighbours.AddLast(neighbour);
                }

            }
        }

        return neighbours;
    }

2 个答案:

答案 0 :(得分:2)

您可以修改DFS以继续使用所有节点,即使它们已被访问过,并且您应该在总距离超过30时停止算法。每次到达“C”时,还应更新搜索路径的计数器

答案 1 :(得分:0)

DFS算法获取两个节点之间所有路径的步骤:

  1. 维护访问过的节点列表,我正在使用访问过的节点列表

  2. 继续在路径中添加节点

  3. 在路径中找到末端节点后,在代码中将其添加到collectio中,这在代码中是在构建路径方法中完成的

            public List<List<RiverNode>> FindAllPathsBetweenTwoNodes(Node startNode, Node endNode, List<string> vistedNodes, List<Node> localpaths)
                    {
                        try
                        {
                            //Mark Current Node As Visited
                            vistedNodes.Add(startNode.Name);
                            if (localpaths.Count == 0)
                            {
                                localpaths.Add(startNode);
                            }
    
                            if (startNode.Name.Equals(endNode.Name))
                            {
                                BuildPath(localpaths);
                            }
    
                            foreach (var node in startNode.GetNeighbours())
                            {
                                if (!vistedNodes.Contains(node.Name))
                                {
                                    localpaths.Add(node);
                                    FindAllPathsBetweenTwoNodes(node, endNode, vistedNodes, localpaths);
                                    localpaths.Remove(node);
                                }
                            }
                            vistedNodes.Remove(startNode.Name);
                            return allPaths;
                        }
                        catch (Exception ex)
                        {
                            throw;
                        }
                    }
    
    
    
                    // <summary>
                    /// Build Path
                    /// </summary>
                    /// <param name="localpath"></param>
                    private void BuildPath(List<RiverNode> localpath)
                    {
                        var localbuilPath = new List<RiverNode>();
                        foreach (var item in localpath)
                        {
                            localbuilPath.Add(item);
                        }
                        allPaths.Add(localbuilPath);
                    }