Java二叉树克隆问题

时间:2011-05-18 10:13:05

标签: java clone binary-tree

我有一个具有以下规范的Java二进制树,我需要克隆它。

public class Item {

    private final String value;
    public final Item left;
    public final Item right;

    ...

}

似乎是一项非常简单的任务令我感到困惑,因为克隆树必须与原始树对象共享相同的单元格而不是被复制。

但是,如果要将项目添加到原始树或克隆树中,则它不能传播到另一个树。即。如果要将新项目添加到原始树中,则它不得出现在克隆树和副项中。

这也需要在没有递归和没有任何循环结构的情况下完成。

所以我想知道是否有人可以想到这样做,因为我不知道从哪里开始?

6 个答案:

答案 0 :(得分:3)

如果在结构中设置写入副本,则可以执行此操作:

/*in Item */
Item add(String value){
   Item item = new Item(this.value);
   if(value.compareTo(this.value)<0){
      item.left = this.left;
      item.right = this.right.add(value);
   }else{
      item.left = this.left.add(value);
      item.right = this.right;
   }
   return item;
}

然后克隆只是将根复制到另一棵树

答案 1 :(得分:1)

Node cloneTree(Node root) {
        Node n1 = new Node();
        n1.value = root.value;
        cloneTree(root, n1);
        return n1;
}

void cloneTree(Node root, Node newNode) {
        if (root == null) {
            return;
        }
        if (root.leftNode != null) {
            newNode.leftNode = new Node();
            newNode.leftNode.value = root.leftNode.value;
            cloneTree(root.leftNode, newNode.leftNode);
        }
        if (root.rightNode != null) {
            newNode.rightNode = new Node();
            newNode.rightNode.value = root.rightNode.value;
            cloneTree(root.rightNode, newNode.rightNode);
        }

}

答案 2 :(得分:0)

您可以为特定节点编写克隆方法。此方法使用当前节点的值创建新节点。该方法的结果将是克隆节点。

在该方法中,您可以递归地调用右侧和左侧节点的clone方法。调用的结果将被设置为克隆节点的左右节点。这应该可以解决问题。

代码看起来像这样

public Item cloneItem() {

    Item cloneLeft = left.cloneItem();
    Item cloneRight = right.cloneItem();
    return new Item(value, cloneLeft, cloneRight);
}

你必须检查左边和/或右边是否设置了我在示例中遗漏的内容。

答案 3 :(得分:0)

左右子树的final没有多大意义。使它们成为最终的,树本质上是不可变的,因此插入操作没有意义。无论如何,这段代码应该有希望使思考过程变暖。

public class Node {
  final String value;
  Node left;
  Node right;

  boolean copyOnWrite; //google it for more information

  public Node(String value,Node left,Node right,boolean copyOnWrite) {
    //blabla
  }

  public Node copy() { //not recursive!
    copyOnWrite = true;
    return new Node(value,left,right,true);
  }

  public Node deepCopy() { //recursive!
    return new Node(value,left.deepCopy(),right.deepCopy(),false);
  }

  public void insert(String value) {
    if (copyOnWrite) {
      copyOnWrite = false;
      left = left.deepCopy();
      right = right.deepCopy();
    }
    //normal tree insert code
  }

因此,调用copy()很快就会生成浅层副本。只有在尝试修改deepCopy()时才会执行{{1}}。实际上,没有必要制作整个树的深层副本,但由于这是作业,我留下(需要多少副本?哪些节点变得“脏”?)作为练习:)

答案 4 :(得分:0)

简单明了的答案是创建一个Cell对象并让树节点引用它而不是节点中单元格的数据。

答案 5 :(得分:0)

这是一个递归的解决方案。 可能仍需要考虑一些边缘情况,但逻辑是正确的。

公共类CloneTree {

public static void main(String[] args)
{

    tNode root=createTree();
    if(root==null)
    {
        return;
    }
    tNode newR=new tNode();
    cloneMyTree(root,newR);
    printTree(newR);



}




private static tNode cloneMyTree(tNode root, tNode newR) {
    if(root==null)
    {
        return null;
    }
    tNode leftSubNode=null;
    tNode rightSubNode=null;

    if(!(root.left==null))
        {
         leftSubNode = new tNode();
          cloneMyTree(root.left, leftSubNode);
        }

    if(!(root.right==null))
    {
     rightSubNode = new tNode();
      cloneMyTree(root.right, rightSubNode);
    }

    newR.left=leftSubNode;
    newR.right=rightSubNode;
    newR.value=root.value;


    return root;




}

public static void printTree(tNode root)
{
    if(root==null)
    {
        System.out.println("NULL");
        return;
    }
    else{
    System.out.println(root.value);
    System.out.println("Left of "+root.value);
    printTree(root.left);

    System.out.println("right of "+root.value);
    printTree(root.right);
    }

}



public static tNode  createTree()
{
bTree myTree=new bTree();
myTree.root = new tNode(1);

myTree.root.left=new tNode(2);
myTree.root.left.left=new tNode(4);
myTree.root.left.right= new tNode(5);

myTree.root.right= new tNode(3);
myTree.root.right.left=new tNode(6);
myTree.root.right.right=new tNode(7);
return myTree.root;

}  

}