BST Level Order Traversal list.clear()和list = new ArrayList

时间:2015-11-04 19:21:40

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

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

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

levelOrder()方法将返回

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

问题:在实施中,我声明了一个名为' listOfLevels'的顶级列表。保存级别列表和名为“等级”的低级列表存储每个级别的节点(我打算清除并跨层次重用)。但是,我注意到如果我在' level'上调用了List.clear()方法。在将其添加到' listOfLevels'之后,我会在“listOfLevels'”中找到空列表。方法的返回值,如下

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

我不确定为什么会这样。根据ArrayList文档," As元素被添加到ArrayList,它的容量会自动增长,"所以我想在使用clear()方法清除以前级别的值后,添加下一级别的节点值会显示在列表中。但这似乎并不奏效。我通过为' level'显式分配一个新的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;
}

2 个答案:

答案 0 :(得分:1)

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

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

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

调用new ArrayList代替clear确实是正确的解决方案。

答案 1 :(得分:1)

当您将ArrayList保存到ArrayLists列表时,您没有复制,因此它保存了相同的变量。这是因为ArrayList是指向内存中某个点的指针;这就是实际被保存的东西。通过清除ArrayList,它会清除内存,这也会影响列表的ArrayList中保存的内存位置。使用新行代替clear。