使用hashmap在java中定向图

时间:2018-04-10 05:16:36

标签: java directed-acyclic-graphs directed-graph

我使用Map数据结构在java中实现了有向图。

目前,我有两个地图数据结构:

  1. 保持每个节点,包含所有度数顶点。
  2. 保持每个节点,包含所有度数顶点。
  3. 我的问题如下: 我想实现一个最短路径算法,给定一个特定节点和一个辅助节点,找到第一个节点到第二个节点之间的最短路径。

    我不确定如何使用Map数据结构来实现它。

    public class NetworkInfluence {
    private int numEdges; //number of edges
    private int numVert;  //number of vertices
    private int numIter;  //number of page rank iterations
    private Map<String, List<String>> AtoB; //out degree of vertices
    private Map<String, List<String>> BtoA; //in degree of vertices
    private Map<String, Double> influenceMap;  //page ranks of vertices
    private Set<String> nodeCounter;        //list of vertices
    
    /**
     * Creates a new PageRank object.  This is used to find the pagerank
     * of a graph represented as an edgelist in a text file.
     * @param fileName Name of text file containing graph edge list.
     * @param eps Convergence parameter for pagerank.
     * @throws FileNotFoundException If text file containing graph cannot be found.
     * @throws IOException If error reading a text file.
     */
    public NetworkInfluence(String fileName) throws FileNotFoundException, IOException {
        numIter = 0;
        numEdges = 0;
        AtoB = new HashMap<String, List<String>>();
        BtoA = new HashMap<String, List<String>>();
        Set<String> nodeCounter = new HashSet<String>();
    
        FileReader fr = new FileReader(fileName);
        BufferedReader b = new BufferedReader(fr);
    
        String line = b.readLine();
        String nodes[];
        List<String> toList;
        List<String> fromList;
        while((line = b.readLine()) != null) { 
            numEdges++;
            nodes = line.toLowerCase().split(" ");
    
            //A->B
            if(!AtoB.containsKey(nodes[0])) {
                toList = new ArrayList<String>();
                toList.add(nodes[1]);
    
                AtoB.put(nodes[0], toList);
            } else {
                toList = AtoB.get(nodes[0]);
                toList.add(nodes[1]);
    
                AtoB.put(nodes[0], toList);
            }
            //B->A
            if(!BtoA.containsKey(nodes[1])) {
                fromList = new ArrayList<String>();
                fromList.add(nodes[0]);
    
                BtoA.put(nodes[1], fromList);
            } else {
                fromList = BtoA.get(nodes[1]);
                fromList.add(nodes[0]);
    
                BtoA.put(nodes[1], fromList);
            }
            nodeCounter.add(nodes[0]);
            nodeCounter.add(nodes[1]);
        }
        this.nodeCounter = nodeCounter;
        numVert = nodeCounter.size();
        b.close();
    

    任何帮助将不胜感激。感谢。

1 个答案:

答案 0 :(得分:0)

如上所述,即使您使用的是哈希映射,也可以使用dijkstra解决它。除了你的结构,你还必须以某种方式获得边缘的成本,如下所示:

Map<String, Map<String, Integer>> costs = new HashMap<>();
...
// where the cost of edge ("node0", "node1") is:
int cost = costs.get("node0").get("node1");

部分od dijkstra可能是这样的(我不关心优化地图访问):

public List<String> path(String node0, String node1) {
        // array to keep trace of visited nodes
        Map<String, Boolean> visited = new HashMap<>();
        // array to keep trace of predecessors of nodes in the path
        Map<String, String> pred = new HashMap<>();
        // initialize maps
        for (String n : nodeCounter) {
            visited.put(n, false);
            pred.put(n, node0);
        }

        // min costs from node0 to any other node, initialized to INFINITE if
        // the nodes are not adjacent
        Map<String, Integer> mincosts = new HashMap<>();
        for (String n : nodeCounter)
            mincosts.put(n, costs.get(node0).get(n));

        // initialize flags of start node
        visited.put(node0, true);
        mincosts.put(node0, 0);

        // iterate until all vertexes or node1 are reached
        for (int i = 0; (i < numVert) && (!visited.get(node1)); ++i) {
            int min = inf;
            String candidate = null;
            for (String n : nodeCounter)
                if (!visited.get(n) && mincosts.get(n) < min) {
                    min = mincosts.get(n);
                    candidate = n;
                }
            if (candidate == null)
                break;
            visited.put(candidate, true);

            for (String n : nodeCounter)
                if (!visited.get(n) && ((mincosts.get(candidate) + costs.get(candidate).get(n)) < mincosts.get(n))) {
                    mincosts.put(n, mincosts.get(candidate) + costs.get(candidate).get(n));
                    pred.put(n, candidate);
                }
        }

        if (!visited.get(node1))
            return null;

        // store the path from node1 to node0, using predecessors
        // map
        String current = node1;
        List<String> path = new ArrayList<>();
        path.add(current);
        while (!current.equals(node0))
            path.add(current = pred.get(current));

        // store the path from node0 to node1
        Collections.reverse(path);

        return path;
    }

实际上,如果你也可以使用第三个库,我建议你寻找像JGraphT这样的图形java库,并将给定的函数用于最小路径。例如,here是Dijkstra JGraphT API的参考。