2012-07-29 96 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