【问题标题】:Find if there is a route between 2 nodes Depth first search查找2个节点之间是否有路由深度优先搜索
【发布时间】:2014-05-03 08:02:25
【问题描述】:

我正在使用深度优先搜索和图表来查找 2 个节点之间是否存在路线。 但是由于某种原因,即使有路径,我的方法也总是会导致错误。

这是我的搜索代码:

static boolean search(Graph g, Node start, Node end)
{

if(start == null || end == null) return false;

start.state = State.Visited;

for(Node u: start.getChildNodes())
{
    if(u.state != State.Visited)
    {
        if(u.equals(end))
        {
            return true;
        }
        else
        {
            u.state = State.Visited;
            search(g,u,end);
        }
    }
}

return false;

}

我这样调用方法:

public static void main(String[] args) {

        Graph gDfs = createNewGraph();

        System.out.println("path between A & B");
        System.out.println(search(gDfs,gDfs.getNode()[0],gDfs.getNode()[1]));
    }

createNewGraph()

public static Graph createNewGraph()
{

Graph g = new Graph();        
Node[] temp = new Node[8];

temp[0] = new Node("A", 3);
temp[1] = new Node("B", 3);
temp[2] = new Node("C", 1);
temp[3] = new Node("D", 1);
temp[4] = new Node("E", 1);
temp[5] = new Node("F", 1);

temp[0].addChildNode(temp[1]);
temp[0].addChildNode(temp[2]);
temp[0].addChildNode(temp[3]);

temp[1].addChildNode(temp[0]);
temp[1].addChildNode(temp[4]);
temp[1].addChildNode(temp[5]);

temp[2].addChildNode(temp[0]);
temp[3].addChildNode(temp[0]);
temp[4].addChildNode(temp[1]);
temp[5].addChildNode(temp[1]);

for (int i = 0; i < 7; i++) 
{
    g.addNode(temp[i]);
}
return g;

}

@amit =>这是你的建议吗?

for(Node u: start.getChildNodes())
        {
            if(u.state != State.Visited)
            {
                if (search(g,u,end)) return true;
            }
        }

【问题讨论】:

  • 见阿米特的回答。另外,请确保 Node.equals() 正确实现,否则在路由存在时也可能会得到 false。

标签: algorithm data-structures graph binary-tree depth-first-search


【解决方案1】:

只处理当前状态总是更好,而不是下一个或上一个(不管是 dfs 还是 bfs)。

boolean search(Graph g, Node current, Node target)
{

    if (current == null || target == null) return false;

    current.state = State.Visited;

    if (current == target) return true;

    for(Node u: current.getChildNodes())
    {
        if(u.state != State.Visited && search(g,u,target))
        {                
            return true;
        }
    }    
    return false;    
}

并且某些顶点的“状态”可能不会被标记为“State.Visited”,即使它可以从“A”实现。它可能会导致一些错误,或错误的复杂度估计。我建议用

检查最坏的情况
void search(Graph g, Node v)
{
    v.state = State.Visited;     

    for(Node u: v.getChildNodes())
    {
        if(u.state != State.Visited)
        {                
            search(g,u);
        }
    }        
}

并检查“B.state”是否为“State.Visited”

【讨论】:

  • 我尝试了第一个实现,它仍然返回 false
  • @fscore 试试第二个。如果 if 也会返回 false - 路径不存在。这是一个类似定义的实现。
  • 我正在按照我的示例尝试 A 和 B 之间的路径,因为 A 和 B 是根和子..肯定有一条路线..
  • 我如何测试第二个,因为没有任何迹象表明是否有路径?
  • @fscore B.state == State.visited 意味着 dfs 以某种方式找到了从 A 到 B 的路。
【解决方案2】:

如果递归调用也产生 true,则它应该以产生 true 结束:

if (search(g,u,end)) return true;

否则,您不会对从它返回的值执行任何操作,只会到达for 循环的末尾并最终产生false

附带说明,检查当前节点是否为目标节点的更好做法不在for 循环中,而是作为它之前的新停止子句。请注意,您的方法对于search(G,start,start) 将失败,尽管每个节点与其自身之间都有一条路径(长度为 0)。

【讨论】:

  • 错过了“其他什么都不做”部分。对不起:)
  • @amit 我应该像在其他部分那样更改哪一行,我用你提到的那一行替换了搜索
  • 我没有追问,我建议的那一行if不应该有追随else,如果条件不成立,你只需要继续下一次迭代.
  • @amit 我明白你的意思,但仍然没有结果。你的意思是 '''for(Node u: start.getChildNodes()) { if(u.state != State.Visited) { if (search(g,u,end)) return true; } } '''
  • @fscore 你把停止子句放在哪里了? (如果当前节点是他的目标节点)
猜你喜欢
  • 1970-01-01
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多