简体   繁体   English

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

[英]Java, connected edges in a directed graph so that the graph is traversable

I am producing (or trying to) a directed graph in java made up of Node s and Edge s. 我正在(或试图)在由NodeEdge组成的Java中生成一个有向图。 This graph represents a dependency tree of what I call Modules (Modules play some role in my program). 此图表示我称为模块的依赖关系树(模块在程序中扮演某些角色)。 Certain modules need to be ran before others within the program and I use a directed graph to represent this. 程序中的某些模块需要先运行,而我使用有向图来表示。 Modules (and Node s) know which other modules must come before them. 模块(和Node )知道哪些其他模块必须位于它们之前。

Currently I take and read a directory and get a ArrayList of Modules and in turn make that into an ArrayList of Node s. 目前,我读取目录并获取Modules的ArrayList,然后将其放入Node的ArrayList中。 My problem is connecting these node s with the node classes addEdge(..) function. 我的问题是将这些nodenodeaddEdge(..)函数连接。 When I call my function (code below) connectNodes(..) I want to create edge objects between the node s so that I can traverse the entire tree, going from node s to node s using edge s. 当我调用函数(以下代码) connectNodes(..)我想在node s之间创建边缘对象,以便可以遍历整棵树,使用edge s从node s到node s。 It seems the the way in which my connectNodes(..) method works I cannot do this. 看来我的connectNodes(..)方法的工作方式无法实现。

The problem is that the outEdge and inEdge HashSet of each Node object returned from connectNodes correctly points to Node with the proper name (representing their upper and lower dependencies), but those Node objects do not have their inEdge and outEdge sets filled to point to the Node above and below them in the tree. 问题是从connectNodes返回的每个Node对象的outEdgeinEdge HashSet正确指向具有正确名称的Node (代表它们的上下依赖性),但是这些Node对象没有填充inEdgeoutEdge集以指向Node上面和下面他们在树上。

So it is as if, each end of every edge points to a copy of another Node object with the proper info but the wrong (by wrong I mean none) edge sets. 如此看来,每个边缘的每一端都指向另一个Node对象的副本,该对象具有正确的信息,但边缘集错误(错误地是我没有意思)。 They should point to the other Node objects in the ArrayList. 它们应指向ArrayList中的其他Node对象。

Node.java Node.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;
    }
}

Edge.java Edge.java

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;
    }
}

The problem function 问题功能

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;
}

EDIT: I think my problem lies in this function meant to clone the array list, it does not take into account the edges pointing to the old Nodes and not the new nodes. 编辑:我认为我的问题在于此功能旨在克隆数组列表,它没有考虑到指向旧节点而不是新节点的边。

public static ArrayList<Node> cloneList(ArrayList<Node> inList)
{
    ArrayList<Node> clonedList = new ArrayList<Node>(inList.size());
    for(Node aNode : inList)
    {
        clonedList.add(new Node(aNode));
    }
    return clonedList;
}

First, when you have HashSet, always override both equals and hashcode. 首先,当您拥有HashSet时,请始终同时覆盖equals和hashcode。

Other than that, the graph seems to be built correctly (note that you are always returning a new list with the same elements as your param). 除此之外,该图似乎已正确构建(请注意,您始终返回的新列表具有与参数相同的元素)。 You can use some Map to eliminate the innermost loop( k ). 您可以使用一些Map消除最里面的loop( k )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM