图:TreeSet没有添加所有边

时间:2017-07-09 17:08:57

标签: java graph set treeset

我正在处理无向图问题。我有一个Node类,其中包含nodeNameList<Edge>。然后我有Edge类,其中包含Node startNode endweight。最后我有一个Graph类,它有一个实例变量Map<String, Node>

我想将所有不同的边添加到集合中,并根据边缘权重按递增顺序对它们进行排序。因此,我选择TreeSet以独特的排序方式存储所有边缘。但是当我调用addAllEdges()时,它并没有添加所有边缘。该图有9个顶点和14个边。但是,treeSet只保存了其中的10个。

enter image description here

代码结构:

图形:

class Graph {
    private Map<String, Node> verticesMap = new HashMap<>();

    public void addEdge(String src, String dest, int weight) {
        Node srcNode = verticesMap.get(src) == null ? new Node(src) : verticesMap.get(src);
        Node destNode = verticesMap.get(dest) == null ? new Node(dest) : verticesMap.get(dest);
        Edge edge = new Edge(srcNode, destNode, weight);
        srcNode.getEdgeList().add(edge);
        verticesMap.put(src, srcNode);
        verticesMap.put(dest, destNode);
    }

    public Set<Edge> addAllEdges() {
        Set<Edge> allEdgesSet = new TreeSet<>(getComparatorBasedOnEdgeWeight());
        for (Node node : verticesMap.values()) {
            for (Edge edge : node.getEdgeList()) {
            // sysout for debugging purpose only
                if(allEdgesSet.add(edge)) {
                    System.out.println("Added edge: " + edge);
                } else {
                    System.out.println("Did not add edge: " + edge);
                }
            }
        }
        return allEdgesSet;
    }

    private Comparator<Edge> getComparatorBasedOnEdgeWeight() {
        return (e1, e2) -> Integer.compare(e1.getWeight(), e2.getWeight());
    }
}

节点

class Node {
    private String name;
    private List<Edge> edgeList;

    public Node(String name) {
        this.name = name;
        edgeList = new ArrayList<>();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Node other = (Node) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return name;
    }
}

边:

class Edge {
    private Node src;
    private Node dest;
    private int weight;

    public Edge(Node src, Node dest, int weight) {
        this.src = src;
        this.dest = dest;
        this.weight = weight;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((dest == null) ? 0 : dest.hashCode());
        result = prime * result + ((src == null) ? 0 : src.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Edge other = (Edge) obj;
        if (dest == null) {
            if (other.dest != null)
                return false;
        } else if (!dest.equals(other.dest))
            return false;
        if (src == null) {
            if (other.src != null)
                return false;
        } else if (!src.equals(other.src))
            return false;
        return true;
    }

    @Override
    public String toString() {
        return src + "-->" + dest + "[" + weight + "]";
    }
}

测试

 public class Test {
        public static void main(String[] args) {
            Graph graph = new Graph();
            graph.addEdge("A", "B", 4);
            graph.addEdge("B", "A", 4);
            graph.addEdge("A", "I", 8);
            graph.addEdge("I", "A", 8);
            graph.addEdge("B", "C", 8);
            graph.addEdge("C", "B", 8);
            graph.addEdge("B", "I", 11);
            graph.addEdge("I", "B", 11);
            graph.addEdge("C", "H", 2);
            graph.addEdge("H", "C", 2);
            graph.addEdge("C", "D", 7);
            graph.addEdge("D", "C", 7);
            graph.addEdge("C", "F", 4);
            graph.addEdge("F", "C", 4);
            graph.addEdge("H", "I", 7);
            graph.addEdge("I", "H", 7);
            graph.addEdge("H", "G", 6);
            graph.addEdge("G", "H", 6);
            graph.addEdge("I", "G", 1);
            graph.addEdge("G", "I", 1);
            graph.addEdge("G", "F", 2);
            graph.addEdge("F", "G", 2);
            graph.addEdge("F", "D", 14);
            graph.addEdge("D", "F", 14);
            graph.addEdge("F", "E", 10);
            graph.addEdge("E", "F", 10);
            graph.addEdge("E", "D", 9);
            graph.addEdge("D", "E", 9);
            graph.addAllEdges();
        }
    }

输出:

Added edge: A-->B[4]
Added edge: A-->I[9]
Did not add edge: B-->A[4]
Added edge: B-->C[8]
Added edge: B-->I[11]
Did not add edge: C-->B[8]
Added edge: C-->H[2]
Added edge: C-->D[7]
Did not add edge: C-->F[4]
Did not add edge: D-->C[7]
Added edge: D-->F[14]
Did not add edge: D-->E[9]
Added edge: E-->F[10]
Did not add edge: E-->D[9]
Did not add edge: F-->C[4]
Did not add edge: F-->G[2]
Did not add edge: F-->D[14]
Did not add edge: F-->E[10]
Added edge: G-->H[6]
Added edge: G-->I[1]
Did not add edge: G-->F[2]
Did not add edge: H-->C[2]
Did not add edge: H-->I[7]
Did not add edge: H-->G[6]
Did not add edge: I-->A[9]
Did not add edge: I-->B[11]
Did not add edge: I-->H[7]
Did not add edge: I-->G[1]

Edges in the TreeSet:
[G-->I[1], C-->H[2], A-->B[4], G-->H[6], C-->D[7], B-->C[8], A-->I[9], E-->F[10], B-->I[11], D-->F[14]]

上面的输出表明它正在迭代28个边(14个顶点* 2)。我无法弄清楚为什么treeSet为那些甚至不存在于集合中的边缘返回false。

1 个答案:

答案 0 :(得分:2)

TreeSet使用Comparator进行排序,但也使用对象的唯一性。它不使用equals()hashCode()

您的Comparator也需要比较节点,例如使用节点名称。

此外,如果您的图表确实是undirected,则您不需要执行graph.addEdge("A", "B", 4) graph.addEdge("B", "A", 4),因为它们代表相同的无向边缘。无向边缘没有“源”或“目的地”。

我建议您更改Edge,将srcdest重命名为node1node2,并确保node1的名称小于node2的名称。

这样,您的Comparator可以简单地比较weightnode1.namenode2.name

private Comparator<Edge> getComparatorBasedOnEdgeWeight() {
    return (e1, e2) -> {
        int cmp = Integer.compare(e1.getWeight(), e2.getWeight());
        if (cmp == 0)
            cmp = e1.getNode1().getName().compareTo(e2.getNode1().getName());
        if (cmp == 0)
            cmp = e1.getNode2().getName().compareTo(e2.getNode2().getName());
        return cmp;
    };
}