【问题标题】:BST Level Order Traversal list.clear() and list = new ArrayListBST 级别顺序遍历 list.clear() 和 list = new ArrayList
【发布时间】:2015-11-04 19:21:39
【问题描述】:

上下文:我在 Java 中创建了一个 BinarySearchTree 类作为学习练习,因为我是 Java 新手。我目前正在编写一种用于级别顺序遍历(BFS)的方法,该方法返回每个级别的节点值列表列表,其中顶级列表索引表示级别编号,每个索引处的下级列表包含该级别的节点值,例如对于这棵树

       F
      / \
     /   \
    /     \
   B       G
  / \       \
 /   \       \
A     D       I
     / \     /
    C   E   H

levelOrder() 方法会返回

[[F], [B, G], [A, D, I], [C, E, H]]

问题:在实现中,我声明了一个名为“listOfLevels”的顶级列表来保存级别列表,并声明一个名为“级别”的较低级别列表来存储每个级别的节点(我打算跨级别清除和重用)。但是,我注意到如果在将它添加到“listOfLevels”之后在“level”上调用 List.clear() 方法,我会在“listOfLevels”中得到空列表作为方法的返回值,就像这样

[[], [], [], []]

我不确定为什么会发生这种情况。根据 ArrayList 文档,“当元素被添加到 ArrayList 时,它的容量会自动增长”,所以我认为在使用 clear() 方法清除上一层的值后,从下一层添加节点值会显示在列表中。不过,这似乎不起作用。我通过每次显式为“级别”分配一个新的 ArrayList 来修复它。

主要问题:如果 ArrayList 会随着元素的添加而自动增长,为什么我每次都需要分配一个新的 ArrayList?为什么在级别之间调用 clear() 会导致顶级列表为空?

以下是二叉搜索树类中的相关位:

public BinarySearchTree<K extends Comparable<K>, V> {
    private Node<K,V> root;
        ...
    public List<List<V>> levelOrder() {
        // see implementation below
    }
        ...
    private static class Node<K extends Comparable<K>, V> {
        private K key;
        private V value;
        private Node<K,V> left;
        private Node<K,V> right; 
            ...
    }
}

这里是levelOrder()方法的实现

public List<List<V>> levelOrder() {
    Queue<Node<K,V>> queue = new LinkedList<Node<K,V>>();
    List<List<V>> listOfLevels = new ArrayList<List<V>>();
    List<V> level = new ArrayList<V>();
    int currLevelCount = 1, nextLevelCount = 0;
    queue.add(root);

    while (!queue.isEmpty()) {
        Node<K,V> node = queue.remove();
        currLevelCount--;
        level.add(node.value);
        if (node.hasLeft()) {
            queue.add(node.left);
            nextLevelCount++;
        }
        if (node.hasRight()) {
            queue.add(node.right);
            nextLevelCount++;
        }
        if (currLevelCount == 0) {
            listOfLevels.add(level);
            //level.clear();    <-- why doesn't this work?
            level = new ArrayList<V>();
            currLevelCount = nextLevelCount;
            nextLevelCount = 0;
        }
    }
    return listOfLevels;
}

【问题讨论】:

    标签: java memory-management arraylist binary-search-tree tree-traversal


    【解决方案1】:

    如果您在level 列表中调用clear,则您正在清除刚刚添加到listOfLevels 的列表,然后您开始重新使用它。

    由于您在调用clear 时从未使用new ArrayList() 分配新的level 列表,而不是创建新的arraylist,因此您实际上是在一次又一次地使用同一个列表。

    而且由于您每次都在清除它,所以listOfLevels 下的列表中永远不会有值。

    调用new ArrayList 而不是clear 确实是正确的解决方案。

    【讨论】:

      【解决方案2】:

      当您将 ArrayList 保存到 ArrayLists 列表时,您并没有制作副本,因此它保存的是相同的变量。这是因为 ArrayList 是指向内存中某个点的指针。这就是实际保存的内容。通过清除 ArrayList 会清除内存,这也会影响 ArrayList of Lists 中保存的内存位置。使用新行而不是清除行。

      【讨论】:

        猜你喜欢
        • 2011-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-14
        • 2017-11-28
        • 2014-07-22
        • 2017-05-08
        • 1970-01-01
        相关资源
        最近更新 更多