Определить размер целого двоичного дерева с помощью рекурсии

у меня есть классы BinaryTreeNode(int value) с его левым и правым дочерним и BinaryTree (int rootVal) с корнем BinaryTreeNode с rootVal в качестве его значения. Я разработал код для вычисления количества узлов в дереве (в классе BinaryTreeNode), но он не работает из-за исключения NullPointerException:

public int size(){
    if(this == null) {    // base case
        return 0;
    } else {
        return 1 + left.size() + right.size();
    }
}

однако другое решение, которое я нашел, с аналогичной стратегией работает:

public int size(BinaryTreeNode refNode){
    if(refNode == null) {    // base case
        return 0;       
    } else {
        return 1 + size(refNode.left) + size(refNode.right); 
    }
}

Я понял, почему мой код выдает исключение (именно потому, что left / right будет указывать на null). Но я хотел бы понять, почему второе решение работает с квази тем же принципом. Заранее спасибо!

3 ответов


в первом примере вы пытаетесь найти размер, Прежде чем проверить null:

сначала ты называешь

left.size()

и size() способ проверить, чтобы увидеть, если объект вы назвали метод это null

if(this == null) {    // base case
    return 0;
...

если left и null, вы получаете NPE, прежде чем попасть в size() метод.

главное, что нужно помнить здесь, это то, что this can никогда быть null. Если он был, во-первых, вы не можете использовать метод. Таким образом, вы фактически не завершали свою рекурсию на null дело, как вы думали, что вы были.


во второй вы проверяете для null первый:

если refNode.осталось null здесь

    return 1 + size(refNode.left) + size(refNode.right); 

the size() метод делает предварительную проверку

if(refNode == null) {    // base case
    return 0;
...

и благополучно возвращает 0.


вы смогли сделать ваше первый метод работает, явно помещая нулевую проверку сначала в каждую ветвь:

public int size(){
    return 1 
        + left == null ? 0 : left.size()    // check for null first
        + right == null ? 0 : right.size(); // check for null first
}

базовый случай организован неправильно; проверка на null в текущем экземпляре нет смысла. Метод следует переписать следующим образом.

public int size(){
    int sizeLeft = 0;
    if (this.left != null)
        sizeLeft = left.size();
    int sizeRight = 0;
    if (this.right != null)
        sizeRight = right.size();
    return 1 + sizeLeft + sizeRight;
}

this не может быть null внутри рабочего класса. Вы получите NPE, потому что узел с left == null или right == null не сможет назвать size() код, потому что указатель не ссылается ни на что.

возможно, ваш код должен быть более оборонительным и проверять, являются ли дети нулевыми, прежде чем пытаться получить их размер:

public int size() {
    int total = 1;
    if (left != null)
        total += left.size();
    if (right != null)
        total += right.size();
    return total;
}