Рекурсия в построении двоичного дерева поиска - PullRequest
0 голосов
/ 25 мая 2020

Ниже приведен код реализации построения двоичного дерева поиска на C ++. Мое замешательство в том, что я не могу отследить стек рекурсии. Рассмотрим дерево ниже. Теперь я хочу удалить узел 10. Итак, это перейдет к строке в коде, которая проверяет, не являются ли и левое, и правое поддерево нулевым, и попытается найти наименьшее значение в правом поддереве, а в данном случае это 11 . и он снова рекурсивно вызовет функцию удаления. Теперь у меня есть одно сомнение - когда remove вызывается снова рекурсивно - сначала он удаляет 11 из этой позиции в исходном дереве и возвращает 11 из функции, полученной функцией first remove в стеке, но затем какая строка в коде действительно обновляется 11 в root. Я действительно не понимаю этого в своей голове. Пожалуйста, помогите мне.

10 / \ 6 12 \ / \ 8 11 15

#include <bits/stdc++.h>
using namespace std;


class BST
{
    public:
      int value;
      BST *left;
      BST *right;

      BST(int val)
      {
          value = val;
          left = NULL;
          right = NULL;
      }


      BST &insert(int val)
      {
          BST *currentNode = this;  //this points to the current object of BST class. For instance if you created
          //root node with value 10. this will store the reference to the root node object
          while(true)
          {
              if (val < currentNode->value)  //go to left subtree
              {
                  if (currentNode->left == NULL)  //if null insert
                  {
                      BST *newNode = new BST(val);
                      currentNode->left = newNode;  //update the address 
                      break;
                  }
                  else 
                  {
                      currentNode = currentNode->left;  //if not null then keep traversing
                  }
              }
              else 
              {
                  if (currentNode->right == NULL)
                  {
                      BST *newNode = new BST(val);
                      currentNode->right = newNode;
                      break;
                  }
                  else 
                  {
                      currentNode = currentNode->right;
                  }
              }
          }

          return *this;  
      }


      bool contains(int val)
      {
          BST *currentNode = this;
          while(currentNode != NULL)
          {
              if (val < currentNode->value)
                  currentNode = currentNode->left;  //if value is less then keep traversing left
              else if (val > currentNode->value)
                  currentNode = currentNode->right; //if value is greater then keep traversing right
              else 
                 return true;
          }

          return false;
      }


      BST &remove(int val, BST *parentNode = NULL)
      {
          BST *currentNode = this;
          while (currentNode != NULL)
          {
              if (val < currentNode->value)
              {
                  parentNode = currentNode;
                  currentNode = currentNode->left;
              }
              else if (val > currentNode->value)
              {
                  parentNode = currentNode;
                  currentNode = currentNode->right;
              }
              //Up until above line the code first searches for the element to be removed
              else 
              {
                  if (currentNode->left != NULL && currentNode->right != NULL)  //this node checks if it has
                  //left and right child both and if yes then find the least value in the right subtree and then
                  //remove that node from that position
                  {
                      currentNode->value = currentNode->right->getMinValue();
                      currentNode->right->remove(currentNode->value,currentNode);
                  }

                  else if (parentNode == NULL) //this is special case of root node where there may be only
                  //left child existing or only right child. If both exist then above logic takes care of that
                  {
                      if (currentNode->left != NULL)
                      {
                          currentNode->value = currentNode->left->value;
                          currentNode->right = currentNode->left->right;
                          currentNode->left = currentNode->left->left;
                      }
                      else if (currentNode->right != NULL)
                      {
                          currentNode->value = currentNode->right->value;
                          currentNode->left = currentNode->right->left;
                          currentNode->right = currentNode->right->right;
                      }
                      else 
                      {} //This is for single node tree. Do nothing
                  }

                  else if (parentNode->left == currentNode)  //this condition if the parent node left child is 
                  //the node to be removed . Then we can do simple one liner and update the node 
                  {
                      parentNode->left = currentNode->left != NULL ? currentNode->left : currentNode->right;
                  }
                  else if (parentNode->right == currentNode)
                  {
                      parentNode->right = currentNode->left != NULL ? currentNode->left : currentNode->right;
                  }

                  break;
              }
          }

          return *this;
      }

      int getMinValue()
      {
          if (left == NULL)
              return value;
          else 
             return left->getMinValue();
      }

      void show()
      {
          BST *currentNode = this;
          cout<<currentNode->value;

      }
};




int main()
{

    int value = 10;
    BST b1(value);
    b1.insert(12);
    b1.insert(6);
    b1.insert(8);
    b1.insert(15);
    b1.insert(11);
    b1.remove(10);
    b1.show();


}
...