Как избежать нулей в строковом представлении двоичного дерева поиска?

#java #binary-tree #binary-search-tree

#java #двоичное дерево #binary-search-tree

Вопрос:

В качестве упражнения по программированию мне нужно переписать некоторые существующие методы и классы, которые составляют двоичное дерево. (Сигнатуры методов и конструкторы должны оставаться неизменными). Почему-то я действительно не понимаю, что я здесь сделал.

Должен ли метод toString быть общедоступным, потому что он перезаписывает метод toString класса объекта? И как я могу избежать возврата нулей?

Вот код, к которому я пришел до сих пор:

Класс дерева

 Node root = null;

void addNode(int val) {
        Node newNode = new Node(val);
        root = newNode.addNode(root, val);
    }
  

Класс узла

 Node(int val) {
    val = val;
    left = null;
    right = null;
}

Node addNode(Node focusNode, int newNodeVal) {

    if (focusNode == null)
        return this;
    if (newNodeVal == focusNode.val)
        return focusNode;
    if (newNodeVal < focusNode.val)
        focusNode.left = this.addNode(focusNode.left, newNodeVal);
    else
        focusNode.right = this.addNode(focusNode.right, newNodeVal);

    return focusNode;
}

public String toString() {
    return this.left   " "   this.val   " "   this.right;
}
  

Ответ №1:

Используйте a StringBuilder для сохранения String представления узла и добавления данных дочерних узлов только в конкретный узел, которого нет null . Вот пример использования инфиксной навигации по узлам:

 public String toString() {
    StringBuilder sb = new StringBuilder();
    if (this.left != null) {
        sb.append(this.left);
        sb.append(' ');
    }
    sb.append(this.val);
    if (this.right != null) {
        sb.append(' ');
        sb.append(this.right);
    }
    return sb.toString();
}
  

Комментарии:

1. this.left Добавляется If . Он автоматически вызовет toString метод. И поэтому он рекурсивно добавляет значения узлов? Это правильно?

2. @TomTomTom да, вы правы. Эта реализация является рекурсивной.

Ответ №2:

 public String toString() {
    if(this.left==null){
        return this.val   this.right;
    } else if (this.right==null){
        return this.left   this.val;
    } else if (this.left == null amp;amp; this.right == null){
        return "";
    } else {
        return this.left   " "   this.val   " "   this.right;
    }
}
  

Вы присваиваете своим узлам значение null для запуска, и ваш метод toString предполагает, что они были изменены. Представьте дерево, в которое вы добавили 5, затем 3. Затем вызывается toString в дереве. Он попытается напечатать узел, 5 — значение, слева — 3, справа — null. При попытке вызвать

 return this.left   " "   this.val   " "   this.right;
  

Вы говорите, чтобы напечатать

 3 5 NULL
  

Ответ №3:

Вы можете инициализировать left и right с пустым Node объектом (с no val ), и когда вы его распечатаете, вы увидите null как val пустой Node :

 Node(Integer val) {
    this.val = val;
    left = new Node(null);
    right = new Node(null);
}
  

Это работает только в том случае, если вы создаете val Integer .

В вашем коде также есть ошибка: val = val останется this.val нетронутым. Вы должны использовать this.val = val;

toString() переопределяется, а не перезаписывается. Он должен возвращать a String , и вы не можете избежать null s, если ваш Node лист.

Что вы можете сделать, так это написать toString() так, чтобы иметь смысл иметь null val такое:

 public String toString() {
    return "#{val = "   val   ", left = "   left   ", right = "   right   "}"
}
  

Пожалуйста, обратите внимание, что это будет рекурсивно пересекать ваше дерево, поэтому для печати вашего дерева вам нужно только позвонить root.toString() .