【发布时间】:2014-06-29 12:25:26
【问题描述】:
我有一个使用列表表示的有向图数据结构(HashMap<Vertex, ArrayList<Vertex>>);源顶点作为键,目标顶点的 ArrayList 作为值。深度优先搜索和 dfs 循环用于遍历图以找到顶点的执行顺序。
执行顺序由setLabel(int i)设置为Vertex对象的标签,并且只有String name字段用于生成hashcode。
我的问题是,dfs 完成后,当我遍历 HashMap [graph.keySet()] 的键时,仍然有几个没有标记的顶点,但是当我迭代时虽然探索的集合是aHashSet<Vertex>,但所有可能的顶点都被标记(准确地)。
这里可能发生什么? (我只能使用 HashMap 来检索顶点的标签)
注意:我相信这与在 HashMaps 中使用可变对象作为键有关。如果不是请纠正我。
/**
* Recursive depth-first search
* @param graph HashMap<Vertex,ArrayList> (list representation)
* @param start starting Vertex
*/
public void dfsR(HashMap<Vertex, ArrayList<Vertex>> graph, Vertex start) {
this.explored.add(start); //a HashSet<Vertex>
ArrayList<Vertex> list = graph.get(start);
if (list != null) {
for (Vertex v : list) {
if (!this.explored.contains(v)) {
this.dfsR(graph, v);
}
}
}
/* First pass-Execution order */
if (!this.secondPass) {
start.setLabel(++this.label);
}
}
/**
* Run DFS on every vertex of the Graph
* @param graph HashMap<Vertex,ArrayList<Vertex>> (list representation)
*/
private void dfsLoop(HashMap<Vertex, ArrayList> graph) {
this.secondPass = false;
this.explored.clear();
this.label = 0;
for (Vertex vertex : graph.keySet()) {
if (!this.explored.contains(vertex)) {
this.dfsR(graph, vertex); /* Recursive dfs */
}
}
}
public class Vertex {
private final String name;
private int label;
public Vertex(String name) {
this.name = name;
this.label = -1;
}
public Vertex(Integer name) {
this.name = String.valueOf(name);
this.label = -1;
}
public String getName() {
return name;
}
/**
* Value(Label) obtained from Topological Ordering
* @param label integer value of the relevant position
*/
public void setLabel(int label){
this.label = label;
}
/**
* @return the Label obtained from the Topological ordering
*/
public int getLabel(){
return this.label ;
}
@Override
public String toString() {
return name;
}
@Override
public boolean equals(Object o) {
if(o == null){
return false;
}
if (o instanceof Vertex) {
Vertex v = (Vertex) o;
return this.name.equals(v.getName());
}
return false;
}
@Override
public int hashCode() {
int hash = 3;
hash = 89 * hash + this.name.hashCode();
return hash;
}}
【问题讨论】:
-
注意:我相信这与在 HashMaps 中使用可变对象作为键有关。 这听起来像是一个合理的猜测。您是否尝试过纠正此问题?
-
注意:您可能应该改用
HashMap<Vertex, ArrayList<Vertex>>。 -
Eug 原始类型。请不要使用它们。
-
您只在
hashCode和equals中使用name- 这是final所以HashMap应该很高兴。 -
@Keppil 即使 Vertex 对象是可变的,设置标签也不会改变 hashCode。所以我相信它是有效的密钥。
标签: java hashmap graph-algorithm hashset