2010-07-03 82 views
3

旧的价值/参考事物。对于Bron-Kerbosch的这种改编,我得到ConcurrentModificationException 。Java递归,用对象调用它 - 如何复制对象?

public int[] bk(ArrayList<Integer> R, ArrayList<Integer> P, ArrayList<Integer> X) { 
    int count[] = new int[n]; 
    int u=0, c = 0; 

    ArrayList<Integer> tempPX = new ArrayList<Integer>(); 
    ArrayList<Integer> newP = P; 
    ArrayList<Integer> newX = X; 
    ArrayList<Integer> newR = R; 

    if (P.isEmpty() && X.isEmpty()) { 
     count[R.size()]++; 
    } else { 

     u = 0; c = 0; // find vertex with largest degree    
     tempPX.addAll(P); tempPX.addAll(X); // P ⋃ X 
     for (Integer v : tempPX) {    
      if (neighbours[v].size() > neighbours[u].size()) { 
       u = c; 
      } 
      c++; 
     } 

     P.removeAll(neighbours[u]); // P \ neighbours[u] 
     for (Integer v : newP) { 

      newR.add(v); // R ⋃ v 

      newP.retainAll(neighbours[v]); // P â‹‚ neighbours[v] 

      newX.retainAll(neighbours[v]); // X â‹‚ neighbours[v] 

      bk(newR, newP, newX); 

      P.remove(v); // removing object 
      X.add(v); // X ⋃ v 
     } 

    } 

    return count; 
} 

在(整数v:newP)的行处发生异常,并在那里发生递归调用。 我需要P.removeAll(neighbours [u]);然后在结果列表中循环,在注释中做内容,并在递归调用中使用PASS COPIES,这样它就不会投诉,并且工作不通过引用并不断修改同一个对象P/X/R。那么如何及何时将其复制?那些第一行..我正在复制的参考不是我... (是的,我知道我“修改”newP然后循环在旧的P,他们只是指向它看起来相同的对象)

读取的答复后

---新代码 -

public int[] bk(List<Integer> r, List<Integer> p, List<Integer> x) { 
    int count[] = new int[n]; 
    int u = 1; 

    List<Integer> tempPX = new ArrayList<Integer>(); 
    List<Integer> newR, newP, newX; 

    if (p.isEmpty() && x.isEmpty()) { 
     count[r.size()]++; 
    } else { 

     // find vertex with largest degree in P U X   
     tempPX.addAll(p); 
     tempPX.addAll(x); 
     for (Integer v : tempPX) {    
      if (neighbours[v].size() > neighbours[u].size()) { 
       u = v; 
      } 
     } 

     p.removeAll(neighbours[u]); // P \ neighbours[u] 
     newP = new ArrayList<Integer>(p); 
     for (Integer v : newP) { 

      r.add(v); // R U v 
      newR = new ArrayList<Integer>(r); 

      p.retainAll(neighbours[v]); // P /\ neighbours[v] 
      newP = new ArrayList<Integer>(p); 

      x.retainAll(neighbours[v]); // X /\ neighbours[v] 
      newX = new ArrayList<Integer>(x); 

      bk(newR, newP, newX); 

      p.remove(v); // removing object 
      x.add(v); // X U v 
     } 

    } 

    return count; 
} 
+0

您可以通过使用小写字母变量来改善您的风格。另外,每行不要做多个声明或分配。 – starblue 2010-07-03 09:56:19

回答

6

正如您已经确定,您正在复制参考,而不是列表。您需要使用旧列表中的条目实例化新的ArrayList对象。

例如

List<Integer> newList = new ArrayList<Integer>(oldList); 

因此,这明确创建了一个新的对象,其中包含对相同元素的引用。

请注意,我通过引用界面List而不是实现 - 通常是一种很好的做法,因为您没有在整个代码库中公开实现。

0

的ArrayList NEWP = P;

这只会创建对同一个ArrayList的第二个引用。复制阵列列表使用

ArrayList newP = new ArrayList(P);

+0

确定一些基于回答评论的改进,但并没有真正获得(正确的方式)“我认为我想要的”。检查最初的帖子。 – Recct 2010-07-03 10:28:53

0

您的第一个& &检查是多余的,原来检查是与X参数?

另外,你在for循环开始处的循环没有任何意义,你在那里做什么?问题是你正在使用计数器(c)和tempPX列表(v)的内容。您使用v来执行检查,但将c作为分配。结果完全取决于数据排序,不会产生任何有意义的结果。

通常情况下,你会使用其中一种,并在检查和分配中使用它。

if (p.isEmpty() && p.isEmpty()) { 
    count[r.size()]++; 
} else { 
    u = 0; c = 0; // find vertex with largest degree 
    tempPX.addAll(p); tempPX.addAll(x); // P U X 
    for (Integer v : tempPX) { 
    if (neighbours[v].size() > neighbours[u].size()) { 
     u = c; 
    } 
    c++; 
    } 

无论你的目标是要找到在temppx列表与邻居的最大用量的指标(滴在赋值的变量c和C++线,使用V)或刚刚找到索引邻居的最大数量,而不对股指任何限制,在这种情况下,你可以使用一个for循环是这样的:

for (int c = 0; c < neighbours.size(); ++c) 

,丢弃temppx列表的任何提及。我的猜测是你想要做第一个案子。

+0

确定固定循环和明显的跛脚错误。现在复制如何?复制首先修改副本,传递副本,然后r p x是那些值,复制它们,修改它们递归传递这些副本,这是我的逻辑。 (neighbors [node]包含节点的邻居集合,因此循环中的索引至关重要) – Recct 2010-07-03 13:31:52