我正在处理无向图问题。我有一个Node
类,其中包含nodeName
和List<Edge>
。然后我有Edge
类,其中包含Node start
,Node end
和weight
。最后我有一个Graph
类,它有一个实例变量Map<String, Node>
。
我想将所有不同的边添加到集合中,并根据边缘权重按递增顺序对它们进行排序。因此,我选择TreeSet
以独特的排序方式存储所有边缘。但是当我调用addAllEdges()
时,它并没有添加所有边缘。该图有9个顶点和14个边。但是,treeSet只保存了其中的10个。
代码结构:
图形:
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。
答案 0 :(得分:2)
TreeSet
使用Comparator
进行排序,但也使用对象的唯一性。它不使用equals()
或hashCode()
。
您的Comparator
也需要比较节点,例如使用节点名称。
此外,如果您的图表确实是undirected,则您不需要执行graph.addEdge("A", "B", 4)
和 graph.addEdge("B", "A", 4)
,因为它们代表相同的无向边缘。无向边缘没有“源”或“目的地”。
我建议您更改Edge
,将src
和dest
重命名为node1
和node2
,并确保node1
的名称小于node2
的名称。
这样,您的Comparator
可以简单地比较weight
,node1.name
和node2.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;
};
}