2010-07-03 53 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