2012-07-29 61 views
4

對於任何Java開發人員來說,這個問題應該相當容易。我發誓在花費了大約2個小時後查了一下,但我真的不明白這個代碼有什麼問題。未深度複製的簡單Java對象

基本上,我正在實施Karger的最小切割算法。它需要我繼續合併圖形中的節點,然後計算結尾處的交叉邊的數量(一個int值)。該算法必須重複n次,始終從起始圖形開始。我的問題是我無法創建我的Graph對象的深層副本,我找不到這個錯誤。

我裁剪了代碼,只是顯示問題,沒有更多,但我仍然無法弄清楚什麼是錯的。這裏的代碼是。

類節點:

public class Node { 
public Integer Data; 


public Node() { 
    Data = 0; 
} 

public Node(Node rhs) { 
    Data = rhs.Data.intValue(); 
} 

public Node(Integer rhs) { 
    Data = rhs.intValue(); 
} 

public void setNode(Integer rhs) { 
    Data = rhs; 
} 

類圖形:

public class Graph { 

public ArrayList<ArrayList<Node>> AdjList; 
public ArrayList<Node> NodeSet; // This contains all the nodes 

public Graph() { 
    AdjList = new ArrayList<ArrayList<Node>>(); 
    NodeSet = new ArrayList<Node>(); 
} 

public Graph(Graph G) { 
    AdjList = new ArrayList<ArrayList<Node>>(); 
    for (ArrayList<Node> L : G.AdjList) { 
     ArrayList<Node> Lcopy = new ArrayList<Node>(); 
     for (Node N : L) { 
      Node copy = new Node(N); 
      Lcopy.add(copy); 
     } 
     AdjList.add(L); 
    } 
} 
    public void addNewAdjList(ArrayList<Node> NodeAdjList) { 
    // Input is the adjacency list of a new node 
    // The first element in the NodeAdjList is the node itself, the rest is the adj nodes 
    AdjList.add(NodeAdjList); 
} 
public static void printAdjList(ArrayList<Node> Adjlist) { 
    Node start = Adjlist.get(0); 
    System.out.print(start.Data + " : "); 
    for (int j=1; j < Adjlist.size(); ++j) { 
     System.out.print(Adjlist.get(j).Data + ", "); 
    } 
    System.out.print("\n"); 
} 

主要:

public class Main { 

/** 
* @param args 
*/ 
public static void main(String[] args) { 
    Node Five = new Node(5); 
    Node Seven = new Node(7); 
    Node One = new Node(1); 

    Graph G = new Graph(); 

    ArrayList<Node> L = new ArrayList<Node>(); 
    L.add(Five); 
    L.add(Seven); 
    L.add(One); 

    G.addNewAdjList(L); 

    Graph R = new Graph(G); 
    R.AdjList.get(0).get(1).setNode(19); // Gets node #1 in the first adj list, i.e. 7 

    Graph.printAdjList(G.AdjList.get(0)); 
    Graph.printAdjList(R.AdjList.get(0)); 

} 

}

輸出:

5:19,1,

5:19,1,

這種困惑的我是誠實的。我明白Java只是傳值,但是對象總是由它們的引用來表示。據我所知,我的G的拷貝構造函數應該總是做一個深層拷貝:我正在遍歷每個鄰接表,然後我正在製作一個Node的深層拷貝。我不明白爲什麼在複製對象上調用.setNode()也會修改原始對象(具有不同的引用)。

1以前的答案似乎走向相同的方向我走了,我在這裏錯過了什麼? :S

回答

5

你的錯誤是在這裏:

ArrayList<Node> Lcopy = new ArrayList<Node>(); 
for (Node N : L) { 
    Node copy = new Node(N); 
    Lcopy.add(copy); 
} 
AdjList.add(L); 

您創建的副本L(稱爲Lcopy),但是你添加的L你克隆的圖。要修復它的最後一行應該是這樣的:

AdjList.add(Lcopy); 

注意:如果你已經爲你的變量,而不是L使用一個合理的名稱此錯誤很可能永遠不會發生!

+0

在Node的構建器中進行實際的複製是否會更好? – 2012-07-29 22:14:01

+0

喜歡這個筆記:] – dantuch 2012-07-29 22:14:02