简体   繁体   中英

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. 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

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

The levelOrder() method would return

[[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). 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

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

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. This didn't seem to work, though. I fixed it by explicitly allocating a new ArrayList for 'level' each time instead.

Main Question : If an ArrayList grows automatically as elements are added, why do I need to allocate a new ArrayList each time? Why does calling clear() between levels result in empty lists for the top-level list?

Here are the relevant bits from the Binary Search Tree class:

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

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.

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.

And since you are clearing it every time, you will never have an values in the lists under listOfLevels .

Calling new ArrayList instead of clear is indeed the correct solution.

When you save your ArrayList to your List of ArrayLists you are not making a copy so it is saving the same variable. This is because an ArrayList is a pointer to a spot in memory; 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. Use your new line instead of the clear.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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