Метод вставки дерева двоичного поиска в Java

В следующем методе вставки для двоичного дерева поиска (BST) левая часть дерева обновляется правильно, но возникает проблема со вставкой значений в правой части. Несмотря на использование отладчика для проверки вывода, метод неправильно добавляет некоторые значения как в левую, так и в правую сторону. Может ли кто-нибудь помочь выявить и устранить проблему? Это меня смутило, так как это мое первое упражнение по двоичному дереву поиска. вопрос

//вот код

public void insert(int number) {
        Node newNode = new Node(number);
        if (isEmpty()) {
            root = newNode;
        }
        Node current = root;
        Node parent;
        while (true) {
            parent = current;
            if (current.data > number) {
                current = current.left;
                if (current == null){
                    parent.left = newNode;
                    return;
                }
            }
            else{
                current = current.right;
                if (current == null){
                    parent.right = newNode;
                    return;
                }
            }
        }
    }

Предоставьте код, который мы можем скомпилировать и запустить (без изменений) и который воспроизводит упомянутую вами проблему.

trincot 13.08.2024 23:59

И конкретные затраты и результаты, а также ожидаемые результаты.

shmosel 14.08.2024 00:02

Конкретно сказать: «Я пытался отладить, но не смог в этом разобраться» бесполезно. SO — это не какая-то ситуация с закрытым домашним заданием, когда вы не можете пройти ворота, если не отладили. Цель отладки — сообщить нам, что нам нужно знать, чтобы помочь вам. Этот код не компилируется сам по себе, вы не предоставили никаких подробностей о том, как и что вы отлаживали и какую мудрость вы от этого получили. Как написано, я не думаю, что этот вопрос можно спасти. если вы все еще не можете понять это - попробуйте еще раз, создайте автономный тестовый пример...

rzwitserloot 14.08.2024 01:04

объясните, какие именно данные вы предоставили, что произошло по сравнению с тем, что вы ожидали, что вы сделали, пытаясь отладить это, что вы узнали и как это вас удивило. «Я просто не могу понять» здесь не работает — если вы отлаживали, где-то в процессе какой-то шаг привел к эффекту, которого вы не ожидали. Потому что в противном случае вы дошли до конца, и ответ будет таким, как вы ожидали: это означало бы, что проблемы вообще нет.

rzwitserloot 14.08.2024 01:05

Чтобы поддержать сказанное в предыдущих комментариях, я предлагаю следующие ресурсы и страницы, на которые они ссылаются: Тур , Как задать хороший вопрос , Другие страницы Справочного центра и Минимальный воспроизводимый пример

Old Dog Programmer 14.08.2024 02:04

«Левая часть дерева обновляется правильно, но существует проблема со вставкой значений в правой части. ... метод неправильно добавляет некоторые значения как в левую, так и в правую сторону». Это неясно. То, как я это прочитал, противоречиво. Вопросы этого типа должны включать примеры. В каждом примере должны быть показаны входные данные, ожидаемый результат и фактический результат или поведение.

Old Dog Programmer 14.08.2024 04:12

Используйте отладчик для пошагового выполнения кода, отслеживая переменные. Когда переменная изменилась так, как вы не ожидали? Когда выполнение берет ветку, которую вы не ожидали?

Old Dog Programmer 14.08.2024 04:14
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
7
50
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

В блоке кода необходимо отредактировать два момента.

  • Завершить процесс, если дерево пусто: после проверки isEmpty(), если дерево пусто, я добавил оператор возврата после установки нового узла в качестве корневого. Это предотвращает ненужное зацикливание.

  • Инициализация родительской переменной: перед циклом я инициализировал родительскую переменную нулевым значением. Это важно для обеспечения правильного обновления родительских и текущих переменных внутри цикла.

      public void insert(int number) {
          Node newNode = new Node(number);
    
          if (isEmpty()) {
              root = newNode;
              return; // End Process If Tree is Empty.
          }
    
          Node current = root;
          Node parent = null; // Initializing the Parent Variable
    
          while (true) {
              parent = current;
              if (current.data > number) {
                  current = current.left;
                  if (current == null) {
                      parent.left = newNode;
                      return;
                  }
              } else {
                  current = current.right;
                  if (current == null) {
                      parent.right = newNode;
                      return;
                  }
              }
          }
      }
    

Надеюсь, это было полезно.

И мне очень жаль, что у меня возникли проблемы с недержанием и ясностью ума, поскольку это мой первый пост.

Ezana 14.08.2024 08:16

@Old Dog Programmer Спасибо за информацию о том, как задать хороший вопрос, поскольку это мой первый раз, и извините за поздний ответ.

Ezana 14.08.2024 08:21

Спасибо, всегда есть мелочи, из-за которых ты теряешь рассудок.

Ezana 14.08.2024 08:23
public void insert(int number) {
    root = insert(root, number);
}

private Node insert(Node current, int number) {
    if (current == null) {
        return new Node(number);
    }

    if (number < current.data) {
        current.left = insert(current.left, number);
    } else if (number > current.data) {
        current.right = insert(current.right, number);
    }

    return current;
}

Объяснение:

  • Базовый случай: если узел current равен null, это означает, что мы нашли правильное место для вставки нового узла, поэтому мы создаем новый узел и возвращаем его.
  • Рекурсивный случай:
    • Если number меньше данных узла current, метод рекурсивно обращается к левому поддереву.
    • Если number больше, он рекурсивно переходит в правое поддерево.
  • Возврат: метод возвращает узел current, чтобы гарантировать сохранение древовидной структуры.

Этот рекурсивный подход должен решить любые проблемы, возникающие при неправильной вставке значений как слева, так и справа. Он упрощает логику за счет естественного обхода дерева на основе сравнения между вставляемым number узлом и данными current узла.

Выбор между использованием итеративного метода и рекурсивного метода вставки узлов в двоичное дерево поиска (BST) зависит от нескольких факторов, включая читаемость, производительность и конкретный контекст, в котором вы работаете. Вот сравнение двух подходов:

Рекурсивный метод

Преимущества:

  1. Читабельность и простота:

    • Рекурсивный метод зачастую более краток и понятен, поскольку он напрямую следует естественной рекурсивной структуре двоичного дерева. Он ясно выражает идею о том, что точка вставки каждого узла определяется путем рекурсивной проверки его левого или правого дочернего элемента.
  2. Меньше кода:

    • Рекурсивный метод обычно требует меньше строк кода и более элегантен, что упрощает его поддержку и снижает вероятность ошибок в сложной логике.
  3. Нет необходимости в отслеживании родителей:

    • В рекурсии вам не нужно вручную отслеживать родительский узел, поскольку рекурсивные вызовы естественным образом обрабатывают обход.

Недостатки:

  1. Риск переполнения стека:

    • В случаях, когда BST становится несбалансированным (например, напоминая связанный список), глубина рекурсии может стать очень большой, что приводит к ошибке переполнения стека в языках с ограниченным размером стека.
  2. Накладные расходы на вызов функции:

    • Рекурсивные вызовы влекут за собой накладные расходы на вызов функций, что может быть немного менее эффективным по сравнению с итеративным подходом, особенно для больших деревьев.

Итерационный метод

Преимущества:

  1. Избегает переполнения стека:

    • Итеративный метод, как правило, более безопасен с точки зрения использования стека, поскольку он не полагается на стек вызовов для обхода. Он больше подходит для очень больших деревьев или случаев, когда дерево может потерять равновесие.
  2. Эффективность:

    • Поскольку итеративный метод позволяет избежать накладных расходов, связанных с вызовами функций в рекурсии, он может быть немного быстрее, особенно для очень больших наборов данных.

Недостатки:

  1. Более сложный код:

    • Итеративный метод обычно требует большего количества кода, включая ручное управление родительскими указателями и более сложный поток управления, что затрудняет чтение и поддержку.
  2. Ручное отслеживание родителей:

    • Вам необходимо вручную отслеживать родительский узел во время обхода, что усложняет работу и увеличивает вероятность возникновения ошибок.

Какой метод удобнее?

  • Для обучения и читаемости: рекурсивный метод более удобен. Его легче понимать, поддерживать и он хорошо согласуется с концептуальной структурой двоичного дерева.

  • Для больших или несбалансированных деревьев: итерационный метод может быть более практичным, поскольку он позволяет избежать потенциальных проблем с переполнением стека и может быть немного более эффективным.

Спасибо, это работает, но у меня вопрос, какой способ удобнее и почему

Ezana 14.08.2024 08:48

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

Pouya Rezaei 14.08.2024 08:53

Не могли бы вы оценить мой ответ? Спасибо!

Pouya Rezaei 14.08.2024 10:40

Другие вопросы по теме