Java,有向图中的连接边,以便图可以遍历

时间:2014-03-30 06:19:17

标签: java algorithm arraylist graph

我正在制作(或尝试)由NodeEdge组成的java中的有向图。此图表示我称之为模块的依赖树(模块在我的程序中扮演一些角色)。某些模块需要在程序中的其他模块之前运行,并且我使用有向图来表示这一点。模块(和Node)知道其他模块必须在它们之前。

目前我接受并读取一个目录并获取模块的ArrayList,然后将其转换为Node的ArrayList。我的问题是将这些nodenodeaddEdge(..)函数相关联。当我调用我的函数(下面的代码)connectNodes(..)时,我想在node之间创建边缘对象,这样我就可以遍历整个树,从node转到{{1}使用node s。似乎我的edge方法的工作方式我无法做到这一点。

问题在于,从connectNodes(..)返回的每个outEdge对象的inEdgeHashSet Node正确指向connectNodes name(表示其上下依赖项),但那些Node个对象没有填充NodeinEdge个集合以指向它们上方和下方的outEdge树。

所以就好像,每个边的每一端指向另一个Node对象的副本,其中包含正确的信息,但是错误的(错误的,我的意思是没有)边集。它们应该指向ArrayList中的其他Node对象。

Node.java

Node

Edge.java

import java.util.ArrayList;
import java.util.HashSet;

public class Node
{
    public String name;
    public HashSet<Edge> inEdges;
    public HashSet<Edge> outEdges;
    public ArrayList<String> deps;

    public Node(String name, ArrayList<String> deps) {
        this.name = name;
        inEdges = new HashSet<Edge>();
        outEdges = new HashSet<Edge>();

        this.deps = deps;
    }
    public Node addEdge(Node node){
        Edge e = new Edge(this, node);
        outEdges.add(e);
        node.inEdges.add(e);
        return this;
    }
    @Override
    public String toString() {
        return name;
    }

    //Used to copy a given node
    public Node(Node inNode)
    {
        this.name = inNode.name;
        this.inEdges = (HashSet<Edge>)inNode.inEdges.clone();
        this.outEdges = (HashSet<Edge>)inNode.outEdges.clone();
        this.deps = inNode.deps;
    }
}

问题功能

public class Edge
{
    public Node from;
    public Node to;
    public Edge(Node from, Node to) {
        this.from = from;
        this.to = to;
    }
    @Override
    public boolean equals(Object obj) {
        Edge e = (Edge)obj;
        return e.from == from && e.to == to;
    }
}
编辑:我认为我的问题在于这个函数意味着克隆数组列表,它没有考虑指向旧节点而不是新节点的边。

private ArrayList<Node> connectNodes(ArrayList<Node> modNodes)
{
    //Final output, a directed graph
    ArrayList<Node> dirGraph = new ArrayList<Node>();
    //For each moduleNode in the argument list
    for(int i = 0; i < modNodes.size(); i++)
    {
        Node curNode = modNodes.get(i);
        //Get the modules dependencies
        ArrayList<String> curDepNames = curNode.deps;
        //For each dependency of this module
        for(int j = 0; j < curDepNames.size(); j++)
        {
            String curDep = curDepNames.get(j);
            Node depNode = null;
            //For each moduleNode in the argument list
            //Find the one that matches this dependency
            for(int k = 0; k < modNodes.size(); k++)
            {
                Node AmodNode = modNodes.get(k);
                //If this modules name is the same as the dependency save it
                //and break from the loop
                if(AmodNode.toString().equals(curDep))
                {
                    depNode = AmodNode;
                    break;
                }
            }
            // If we didn't find the modules dependency then there is an error
            // We are missing a dependency
            if(depNode == null)
            {
                // Throw missing dependency error! ? Do we stop what were doing?
                modCheckStat = Messages.SetConfig.MODULE_MISSINGDEP;
                return null;
            }
            //Otherwise connect an edge between the current ModuleNode and its dependency
            curNode = curNode.addEdge(depNode);
        }
        //Add this node and its dependency to the final array
        dirGraph.add(curNode);
    }
    return dirGraph;
}

1 个答案:

答案 0 :(得分:1)

首先,当你有HashSet时,总是覆盖equals和hashcode。

除此之外,图形似乎是正确构建的(请注意,您总是返回一个与您的参数具有相同元素的新列表)。您可以使用一些Map来消除最内层的循环(k)。