【问题标题】:Merging two binary trees合并两个二叉树
【发布时间】:2019-11-13 13:49:48
【问题描述】:

我想将一棵树与另一棵树合并,t。如果有重叠的数据,我想把它们加在一起。这是我现在的代码。我不明白如何仅使用参数 t 来执行此合并功能。合并不是通常有两个参数吗?

public class TreeFunctions {

   private TreeNode root;

   public TreeFunctions(TreeNode root) {
        this.root = root;
   }

   public TreeNode merge(TreeNode t) {
        TreeNode curr = this.root;
        if (curr == null) {
            return t;
        }

        if (t == null) {
            return curr;
        }

        curr.data += t.data;
        curr.left = merge(t.left);
        curr.right = merge(t.right);
        return curr;
   }
}

public class TreeNode{
    TreeNode left;
    TreeNode right;
    int data;

    public TreeNode(int data) {
        this.data = data;
    }
    public TreeNode(int data, TreeNode left, TreeNode right) {
        this.data = data;
        this.left = left;
        this.right = right;
    }

    public static String inOrder(TreeNode a) {
        if(a == null) return "";
        else return inOrder(a.left).trim() + " " + a.data + " " + inOrder(a.right).trim();
    }
}

编辑 我的合并测试:

public void testMerge2() {
        TreeFunctions c = new TreeFunctions(new TreeNode(5, new TreeNode(2), null));
        TreeNode d = new TreeNode(2, new TreeNode(2), new TreeNode(1));
        TreeNode res2 = c.merge(d);
        assertEquals(TreeNode.inOrder(res2).trim(), "4 7 1");
    }

public void testMerge3() {
        TreeFunctions c = new TreeFunctions(new TreeNode(5, new TreeNode(2), null));
        TreeNode res2 = c.merge(null);
        assertEquals(TreeNode.inOrder(res2).trim(), "2 5");
    }

public void testMerge4() {
        TreeFunctions c = new TreeFunctions(new TreeNode(1, new TreeNode(2, new TreeNode(5), null), null));
        TreeNode res2 = c.merge(new TreeNode(1, null, new TreeNode(2, null, new TreeNode(5))));
        assertEquals(TreeNode.inOrder(res2).trim(), "5 2 2 2 5");
    }

【问题讨论】:

  • 好吧,您找到的这段代码从 Node 对象 (1) 调用方法,目标 Node 对象 (2) 作为参数给出。就像这样:node1.merge(node2); node1 和 node2 是您正在谈论的两个输入。由于合并是一个递归函数,它从目标节点对象(2)一直向下,但它停留在调用者节点对象(1)上,因此它将所有数据收集/合并到调用者节点对象的数据上,一直到从目标节点对象 (2) 开始的树路径的底部。确保这是您想要的。
  • @AntiqTech 是的,这就是我想要的。如果我有两棵树,a 和 b,我希望在调用 a.merge(b) 时将 b 的数据复制到 a 的数据。但是,由于某种原因,我的代码无法正常工作,我得到了 StackOverflowError
  • 你能分享 StackOverflowError 的堆栈跟踪吗?
  • @ashpcj24 左/右链接可能存在问题。递归被调用,直到它到达一个结束节点。也是对我之前所说的更正:数据是在调用者的 root.data => this.root.data 上收集的。我不明白这部分。 this.root 是调用者节点的父节点还是树的根节点?无论如何。如果你得到stackoverflow那么你错过了停止条件=> 1:this.root为null 2:给定的目标节点为null。

标签: java merge tree binary binary-tree


【解决方案1】:

我已根据您的回复编辑了我的答案。我相信这就是您想要的。请尝试并告诉我。

在代码中,函数对于 t1 和 t2 都下降了一层,因此合并总是发生在同一层和同一侧(左-左/右-右)。

 public TreeNode merge(TreeNode t) {
        TreeNode curr = this.root; 
        merge2(curr,t);
        return curr;
   }
   public  void merge2(TreeNode t1,TreeNode t2) {
        if(t2==null)
            return;
        t1.data += t2.data;
        if(t2.left!=null)
        {
            if(t1.left==null)
                t1.left = new TreeNode(0);
            merge2(t1.left,t2.left);
        }
        if(t2.right!=null)
        {
            if(t1.right==null)
                t1.right = new TreeNode(0);
            merge2(t1.right,t2.right);
        }

   }

【讨论】:

  • 如果t(新树)为空,我不想返回curr(当前树),因为它没有要复制的数据吗?但是,将 curr 更改为 ```null` 似乎适用于该特定测试,但对于我刚刚添加到我的帖子中的测试,我仍然会收到 StackOverflowError。
  • 你已经有了第一次调用合并的根节点。在所有递归调用结束后返回那个。当您尝试在参数为 null 时返回 curr 时,会创建一个无限循环,因为以下行:“curr.left = merge(t.left);”和“ curr.right = merge(t.right);”从第二级递归调用开始。所以递归调用并没有结束。我现在正在查看新代码。当我有解决方案时,我会添加评论。
  • 你总是从 merge() 返回 "curr" 并且 "curr" 总是同一个对象。所以不可避免地你执行任务:curr.left = curr,curr.right = curr。我第一次错过了这个。所以只要你从merge中返回curr,就会进入死循环。当前的算法不会产生你想要的东西。根据我对示例测试结果的理解,您想要逐级节点到节点(obj1.leftnode 合并 obj2.leftnode obj1.rightnode 合并 obj2.rightnode 等)。
  • 我该如何纠正?我认为这就是 curr.left = merge(t.left);和 curr.right = merge(t.right);做。
  • 我已经修改了答案。请看看这个答案试试看,让我知道结果。
猜你喜欢
  • 1970-01-01
  • 2020-01-18
  • 1970-01-01
  • 2011-11-24
  • 2021-09-08
  • 1970-01-01
  • 2020-07-12
  • 1970-01-01
  • 2015-05-25
相关资源
最近更新 更多