Depth First Search正在运行java.lang.OutOfMemoryError

时间:2013-02-07 02:49:52

标签: java out-of-memory

当我在无向图上使用深度优先搜索来确定node1是否可以访问node2时,我遇到了java.lang.OutOfMemoryError。代码如下所示。 (打算删除一些不相关的细节。)

    //definition of nodes and edges
    Set<Node> nodes = new HashSet<Node>();
    Map<Node, Set<Node>> edges = new HashMap<Node, Set<Node>>();

    //method to determine if node1 is reachable to node2    
    public boolean isReachable(int p1, MethodNode m1, ClassNode c1, int p2, MethodNode m2, ClassNode c2) {  
            Node node1 = new Node (p1,m1,c1);
        Node node2 = new Node (p2,m2,c2);

            Stack<Node> stack = new Stack<Node>();

        stack.push(node1);
        while(!stack.isEmpty()){

            Node current = null;
            current = stack.pop();
                    //test current node, if its child nodes contains node2, return true
                    //otherwise, push its child nodes into stack
            for(final Node temp : edges.get(current)){
                if(temp.equals(node2)){
                    return true;
                }
                else{
                    stack.push(temp);
                }
            }
        }
        return false;
}

我猜必须有一些内存耗尽的无限调用,但我无法找到它。

4 个答案:

答案 0 :(得分:4)

看起来你的代码很容易追逐它自己的尾巴:如果一个图形包含一个循环,你的代码将耗尽堆栈,因为在将它推入堆栈之前它不会检查顶点是否已经被探索过。

Basic DFS要求您维护一组探索顶点,并仅在未探测到顶点的情况下探索顶点。将此集添加到程序中应解决内存不足问题。

答案 1 :(得分:2)

这是问题

for (final Node temp : edges.get(current)){
    if(temp.equals(node2)){
        return true;
    } else {
        stack.push(temp);
    }
}

这将推送堆栈中的所有邻居,然后取出其中一个邻居,将其所有邻居推送到堆栈(包括您开始的邻居),等等无限制地进行。您需要将节点标记为已访问,因此不会发生这种情况。唯一不会出现无限循环的情况是,您要查找的节点与您开始的节点直接相邻,或者路径上的节点是否以正确的顺序放入堆栈中纯粹的机会。

答案 2 :(得分:1)

使用您的算法,如果图形有一个循环,它将继续将循环元素推入堆栈,直到内存不足为止。您需要跟踪已经探索过的节点,并避免将它们推入堆栈。有几种标准算法可以做到这一点(A * 和Dijkstra浮现在脑海中)。有关详细信息,请参阅depth first search上的维基百科文章。

答案 3 :(得分:0)

尝试使用额外的

  

列表与LT;节点&gt; traversed = new ArrayList&lt;节点&gt;();

在此,您可以将要推送的节点保持在堆栈中。 在将其推入堆栈之前执行1步

if(!traversed.contains(temp)) {
stack.push(temp);
}