新的HashMap指向旧的HashMap

时间:2013-04-30 18:11:51

标签: java hashmap

我正在尝试使用带整数键的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);
        }

2 个答案:

答案 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);          
      }
    }
  }
}