【问题标题】:Binary Tree Node values change after adding them to ArrayList将二叉树节点值添加到 ArrayList 后会发生变化
【发布时间】:2017-01-04 04:48:17
【问题描述】:

首先,我知道必须在每次迭代中创建一个新的 Tree 实例,以免重用相同的对象,并且还有静态对象作为 thisthis 线程通知。我想我已经为此检查了代码的每一部分。

所以,我正在测试下面的代码。关于它的作用的一些信息:

第一个循环遍历根节点列表,其子节点形成二叉树。我为每个根节点创建一个树对象并将其添加到其中,该对象还包含两个数组列表,一个用于树中的所有节点,另一个用于叶子。在循环中,我还为每棵树中的每个叶子随机设置数字,从 1 到 n(其中 n 是树中的叶子数)并将树添加到 arrayList : possibleTrees。

问题: 在第一个循环中,当我遍历每棵树的叶子并打印它们的数字时,它会相应地打印它们。但是在它完成并且我遍历打印所有树叶的可能树之后,许多值发生了变化。

这是一棵有 4 片叶子的树的代码及其下方的输出。顶部打印两次,因为一个是整数数组列表,第二个是直接从节点打印值

编辑:链接到Tree,Node

Edit2:添加了 alltopologies 类 (http://) pastebin.com/sB9UV8T6

    ArrayList<Tree> possibleTrees = new ArrayList<Tree>();
    ArrayList<Integer> numbers = new ArrayList<Integer>();        
    for (int i = 0; i < numNodes; i++) {
        numbers.add(i + 1);
    }
    for (Node n : allTopologies.allBinaryTrees(numNodes)) {
        Tree tree = new Tree();

        tree.setNodesLists(n);

        Collections.shuffle(numbers);
        tree.setleafNums(n, numbers);
        tree.setRoot(n);

        possibleTrees.add(tree);

        System.out.println(numbers);
        System.out.print("[");
        for (Node l : tree.getLeaves()) {

            System.out.print(l.getLeafNum() + ", ");
        }
        System.out.println("]");
        System.out.println("");

    }
    System.out.println("-------------------------------");
    for (Tree t : possibleTrees) {
        System.out.print("[");
        for (Node l : t.getLeaves()) {

            System.out.print(l.getLeafNum() + ", ");
        }
        System.out.println("]");
        System.out.println("");
    }

输出:
[3、2、1、4] [3, 2, 1, 4, ]

[2, 4, 1, 3] [2, 4, 1, 3, ]

[2, 4, 1, 3] [2, 4, 1, 3, ]

[1, 3, 2, 4] [1, 3, 2, 4, ]

[3, 4, 2, 1] [3, 4, 2, 1, ]


[2, 2, 1, 4, ]

[2, 4, 1, 3, ]

[2, 4, 1, 3, ]

[1, 3, 2, 1, ]

[3, 4, 2, 1, ]

提前致谢!

【问题讨论】:

  • 一定有什么解释。我还没有在你发布的代码中找到它。看看您是否可以在 Minimal, Complete, and Verifiable example 中重现不需要的行为。
  • 我仍然无法编译您的代码 - 缺少太多内容。但是,您的问题的一部分可能是方法 Node.isExternal() - 如果它有零个子节点或如果它有一个子节点,它会返回 true。
  • @OleV.V.我确实尝试省略尽可能多的代码,并且我认为它可能是 Collections.shuffle 部分,但我无法验证它。
  • @ThomasKläger 我添加了缺少的部分代码,我想您现在可以尝试编译它。我不得不将第三个链接放在括号中,因为我无法发布它。另外,我不认为这是问题所在,从 OR 切换到 AND 在这里不会有什么不同,因为没有子节点的唯一节点是叶子。
  • 我已经编译了你的 CreateAlTopologies 类,但是问题中的 Tree、Node 和 sn-p 都没有(我将它粘贴到 main 方法中)。举一个例子,您正在调用tree.setRoot(),但您的Tree 类没有定义setRoot 方法。还有很多其他问题。

标签: java loops arraylist tree


【解决方案1】:

为了让您的算法能够在您的树中运行,不得共享节点。

但是在allBinaryTrees() 的内部循环中,您可以创建具有共享节点的树:

    for (Node lt : possibleLeftSubtrees) {
        for (Node rt : possibleRightSubtrees) {
            // make a tree of a node with lt and rt as subtrees,
            // and add it to the result
            result.add(new Node(i,lt, rt));
        }
    }

如果possibleLeftSubtrees 有一个节点,而possibleRightSubtrees 有两个节点,则创建两棵共享左节点的结果树。


顺便说一句,你的Tree.clone() 方法坏了:

Node b = new Node(2);
Node a = new Node(1, b, null);
b.setParent(a);
System.out.println(a.clone());

将引发StackOverflowError,因为克隆a 意味着克隆其左孩子b,这意味着克隆其父a,这意味着......添加无限。

【讨论】:

  • Da**,我在另一个问题中提供了损坏的代码。那时我不知道不重用节点是要求,但我应该知道这可能会带来问题。对不起,我没有警告你。
  • 我认为可能是这样,但由于我为每个叶子创建了一个新节点,我认为这不是问题。关于如何分别创建每个节点但获得相同结果的任何建议?感谢克隆提示顺便说一句
  • 在我看来很明显:在@ThomasKläger 引用的代码中,对ltrt 进行深层复制并将副本传递给new Node()
  • 谢谢大家,现在可以为每棵树制作单独的节点了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多