我正在尝试使用带整数键的HashMap和值的ArrayList来实现图算法。
键是顶点,ArrayList是连接到键顶点的所有顶点。
我正在使用黑名单来跟踪我去过的地方。如果该项目在黑名单中,我还没有访问过该顶点。这段代码的问题是我必须能够在程序运行时多次调用搜索。我正在做的是将黑名单指向带有顶点的图形。然后,当我访问顶点时,我删除了blackList中的值。问题是,blackList指向原始图中的值。因此,当我再次运行搜索时,原始图形缺少我之前搜索过的所有顶点。
TL:DR问题是:我如何创建一个没有指向的新的相同HashMap。
我知道我可以遍历HashMap并复制每个条目,但如果我正在进行大量搜索(大量搜索!),它会变慢。如果这是唯一的方法,我就不会这么做了。
//The class variables used for this search
HashMap<Integer, ArrayList<Integer>> mapBlacklist;
Queue<Integer> line = new PriorityQueue<Integer>();
int searchFor;
boolean areTheyConnected;
//The constructor I'm using
GraphSearch(HashMap<Integer, ArrayList<Integer>> graph, int match){
mapBlacklist = new HashMap<Integer, ArrayList<Integer>>(graph);
searchFor = match;
}
//The search method.
void numberOne(int start, HashMap<Integer, ArrayList<Integer>> graph){
if(graph.get(start).contains(this.searchFor)){
this.areTheyConnected = true;
}
else{
while(!this.mapBlacklist.get(start).isEmpty()){
this.line.add(this.mapBlacklist.get(start).get(0) ;
this.mapBlacklist.get(start).remove(0);
}
}
if(!this.line.isEmpty() && !this.areTheyConnected){
numberOne(this.line.remove(), graph);
}
}
主要方法:
/* What it looks like in the command line to see if vertices 2 5 are connected:
1 2 5
To close the program:
0
*/
boolean keepGoing = true;
while(keepGoing){
Scanner sc = new Scanner(System.in);
int number0 = Integer.parseInt(sc.next());
if(number0 == 0){
keepGoing = false;
sc.close();
}
else if(number0 == 1){
int number1 = Integer.parseInt(sc.next());
int number2 = Integer.parseInt(sc.next());
// GraphSearch gsearch = new GraphSearch(graph, number2);
GraphSearch gsearch = new GraphSearch(mapGraph, number2);
gsearch.numberOne(number1, mapGraph);
System.out.println(gsearch.areTheyConnected);
}
答案 0 :(得分:0)
为什么你首先需要这个mapBlacklist?
我可以从您的算法中看到,您可以使用您的队列迭代(递归)遍历所有未访问的项目。
在循环中:
while(!this.mapBlacklist.get(start).isEmpty()){
this.line.add(this.mapBlacklist.get(start).get(0) ;
this.mapBlacklist.get(start).remove(0);
}
只是不要使用黑名单,也不要从图中删除任何内容。您只能迭代当前顶点中的列表,并将其中的所有项添加到队列中。
是否有意义?
答案 1 :(得分:0)
我发现你使用mapBlackList
令人困惑的方式,我认为这种混乱会导致你的问题。
您无需知道地图的结构以防止重新访问,只需知道您在此搜索过程中访问过的内容。因此,为什么不简单地保留到目前为止访问过的Set<Integer>
个顶点,而不是在构造函数中创建整个图形的浅表副本?你的搜索方法比如:
void numberOne(int start, HashMap<Integer, ArrayList<Integer>> graph){
visited.add(start);
if(graph.get(start).contains(this.searchFor)){
this.areTheyConnected = true;
return;
}
else{
for (Integer destination : graph.get(start)) {
if (!areTheyConnected && !visited.contains(destination)) {
numberOne(destination, graph);
}
}
}
}