繁体   English   中英

BST级别订单遍历list.clear()和list = new ArrayList

[英]BST Level Order Traversal list.clear() and list = new ArrayList

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

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

levelOrder()方法将返回

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

问题 :在实现中,我声明了一个名为“ listOfLevels”的顶级列表来保存级别列表,并声明一个名为“ level”的低级列表来存储每个级别的节点(我打算在各个级别之间进行清除和重用) )。 但是,我注意到,如果在将它添加到“ listOfLevels”后在“ level”上调用List.clear()方法,我将在“ listOfLevels”内获取该方法的返回值的空列表,如下所示

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

我不确定为什么会这样。 根据ArrayList文档,“当将元素添加到ArrayList时,其容量会自动增长”,因此我认为在使用clear()方法清除上一级的值之后,将在下一级添加节点值会显示在列表中。 不过,这似乎没有用。 我通过每次都为“级别”显式分配一个新的ArrayList来解决此问题。

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

以下是Binary Search Tree类中的相关位:

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;
}

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

由于在调用clear而不是创建新的arraylist时,永远不会使用new ArrayList()分配新的level列表,因此有效地重复使用了相同的列表。

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM