简体   繁体   English

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

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

Context : I created a BinarySearchTree class in Java as a learning exercise since I'm new to Java. 上下文 :由于我是Java新手,因此我在Java中创建了BinarySearchTree类作为学习练习。 I'm currently writing a method for a level-order traversal (BFS) that returns a list of lists of node values for each level, where the top-level list index represents the level number and the lower-level list at each index contains the node values for that level, eg for this tree 我目前正在编写一种用于级别顺序遍历(BFS)的方法,该方法返回每个级别的节点值列表的列表,其中顶级列表索引表示级别编号,而每个索引下级列表包含该级别(例如,此树)的节点值

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

The levelOrder() method would return levelOrder()方法将返回

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

Problem : In the implementation, I declare a top-level list called 'listOfLevels' to hold the lists of levels and a lower-level list called 'level' to store the nodes at each level (which I intended to clear and reuse across levels). 问题 :在实现中,我声明了一个名为“ listOfLevels”的顶级列表来保存级别列表,并声明一个名为“ level”的低级列表来存储每个级别的节点(我打算在各个级别之间进行清除和重用) )。 However, I noticed that if I called the List.clear() method on 'level' after adding it to 'listOfLevels', I would get empty lists inside 'listOfLevels' for the method's return value, like this 但是,我注意到,如果在将它添加到“ listOfLevels”后在“ level”上调用List.clear()方法,我将在“ listOfLevels”内获取该方法的返回值的空列表,如下所示

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

I'm not sure why this happens. 我不确定为什么会这样。 According to the ArrayList documentation, "As elements are added to an ArrayList, its capacity grows automatically," so I figured adding node values from the next level would show up in the list after clearing the previous level's values using the clear() method. 根据ArrayList文档,“当将元素添加到ArrayList时,其容量会自动增长”,因此我认为在使用clear()方法清除上一级的值之后,将在下一级添加节点值会显示在列表中。 This didn't seem to work, though. 不过,这似乎没有用。 I fixed it by explicitly allocating a new ArrayList for 'level' each time instead. 我通过每次都为“级别”显式分配一个新的ArrayList来解决此问题。

Main Question : If an ArrayList grows automatically as elements are added, why do I need to allocate a new ArrayList each time? 主要问题 :如果ArrayList随着添加元素而自动增长,为什么每次都需要分配一个新的ArrayList? Why does calling clear() between levels result in empty lists for the top-level list? 为什么在级别之间调用clear()会导致顶级列表为空列表?

Here are the relevant bits from the Binary Search Tree class: 以下是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; 
            ...
    }
}

And here is the levelOrder() method implementation 这是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;
}

If you call clear on the level list, you are clearing the list that you have just added to the listOfLevels , and then you start to re-use it. 如果在level列表上调用clear ,则将清除刚刚添加到listOfLevels的列表,然后开始重新使用它。

Since you never allocate a new level list with new ArrayList() when you call clear instead of creating a new arraylist, you are effectively using the same list over and over again. 由于在调用clear而不是创建新的arraylist时,永远不会使用new ArrayList()分配新的level列表,因此有效地重复使用了相同的列表。

And since you are clearing it every time, you will never have an values in the lists under listOfLevels . 而且由于您每次都在清除它,因此listOfLevels下的列表中将永远不会有值。

Calling new ArrayList instead of clear is indeed the correct solution. 调用new ArrayList而不是clear确实是正确的解决方案。

When you save your ArrayList to your List of ArrayLists you are not making a copy so it is saving the same variable. 当您将ArrayList保存到ArrayList列表时,您没有进行复制,因此将保存相同的变量。 This is because an ArrayList is a pointer to a spot in memory; 这是因为ArrayList是指向内存中某个点的指针。 this is what is actually being saved. 这就是实际保存的内容。 By clearing the ArrayList it clears the memory which also affects the saved memory location in your ArrayList of Lists. 通过清除ArrayList,它会清除内存,这也会影响ArrayList of Lists中保存的内存位置。 Use your new line instead of the clear. 使用新行而不是清除行。

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

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