我有一个具有以下规范的Java二进制树,我需要克隆它。
public class Item {
private final String value;
public final Item left;
public final Item right;
...
}
似乎是一项非常简单的任务令我感到困惑,因为克隆树必须与原始树对象共享相同的单元格而不是被复制。
但是,如果要将项目添加到原始树或克隆树中,则它不能传播到另一个树。即。如果要将新项目添加到原始树中,则它不得出现在克隆树和副项中。
这也需要在没有递归和没有任何循环结构的情况下完成。
所以我想知道是否有人可以想到这样做,因为我不知道从哪里开始?
答案 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;
}
}