【问题标题】:C++ Delete node from binary search treeC++ 从二叉搜索树中删除节点
【发布时间】:2016-10-26 12:51:06
【问题描述】:

我已经建立了一个二叉搜索树,并插入了一些随机值节点。我正在尝试实现一个删除节点的功能,但由于某种原因它不起作用。尝试删除给定节点时,似乎已删除节点的父节点和已删除节点的子节点不会“连接”。

谁能看到我做错了什么?我已经尝试多次调试程序以查看我的错误在哪里,但我不明白如何将父母和孩子联系在一起。

这是我的程序:

#include <iostream>
using namespace std;

struct Node
{
    int data;   
    Node* left; 
    Node* right;
};

Node* insertNode(Node* root, int n);
Node* newNode(int d);
Node* deleteNode(Node* root, int d);
Node* findMin(Node* root);

int main()
{
    int num;
    Node* rootPtr = NULL;
    Node* min;

    rootPtr = insertNode(rootPtr, 15);
    rootPtr = insertNode(rootPtr, 10);
    rootPtr = insertNode(rootPtr, 20);
    rootPtr = insertNode(rootPtr, 24);
    rootPtr = insertNode(rootPtr, 7);
    rootPtr = insertNode(rootPtr, 25);
    rootPtr = insertNode(rootPtr, 5);

    rootPtr = deleteNode(rootPtr, 7);

    cout << "\nEnter a number to search for: ";
    cin >> num;
    if(search(rootPtr, num))
        cout << "\nFound.";
    else
        cout << "\nNot found.";

    cout << endl;
    return 0;
}

Node* insertNode(Node* root, int n)
{
    if(root == NULL)                                
        root = newNode(n);                          
    else if(n <= root->data)                        
        root->left = insertNode(root->left, n);     
    else if(n > root->data)                         
        root->right = insertNode(root->right, n);
    return root;                                    
}

Node* newNode(int d)
{
    Node* newNode = new Node();             
    newNode->data = d;                      
    newNode->left = newNode->right = NULL;
    return newNode;                         
}

bool search(Node* root, int d)
{
    if(root == NULL)                    
        return false;
    else if(root->data == d)            
        return true;
    else if(d < root->data)             
        return search(root->left, d);   
    else if(d > root->data)             
        return search(root->right, d);  
}

Node* deleteNode(Node* root, int d)
{
    if(root == NULL)
        return root;
    else if(d < root->data)
        deleteNode(root->left, d);
    else if(d > root->data) 
        deleteNode(root->right, d);
    else
    {
        if(root->left == NULL && root->right == NULL)
        {
            delete root;
            root = NULL;
        }
        else if(root->left == NULL)     
        {
            Node* temp = root;      
            root = root->right;         
            delete temp;                
        }
        else if(root->right == NULL)    
        {
            Node* temp = root;          
            root = root->left;          
            delete temp;                
        }
        else
        {
            Node* temp = findMin(root->right);
            root->data = temp->data;            
            root->right = deleteNode(root->right, temp->data);
        }
    }
    return root;
}

Node* findMin(Node* root)
{
    if(root == NULL)
        cout << "\nThe tree is empty.";
    else
    {
        Node* temp = root;          
        while(temp->left != NULL)   
            temp = temp->left;      
        return temp;                
    }
}

【问题讨论】:

    标签: c++ binary-search-tree


    【解决方案1】:

    deleteNode() 函数中,节点未在递归的返回路径中连接。您可能需要像处理insertNode() 一样使用函数的返回值。例如,

    else if(d < root->data)
        deleteNode(root->left, d);
    else if(d > root->data) 
        deleteNode(root->right, d);
    

    可能是(类似的)

    else if(d < root->data)
        root->left = deleteNode(root->left, d);
    else if(d > root->data) 
        root->right = deleteNode(root->right, d);
    

    另外,findMin() 的调用者可能需要最小节点及其父节点。让它同时返回。在deleteNode() 中,您可能需要将 parent 的子指针之一设置为 NULL。

    【讨论】:

      【解决方案2】:

      删除节点时,还需要将存储在父节点中的指针设置为NULL。

      假设您有节点 P 和 C,其中 P.left=C,C 是叶节点。您的代码将为 C 释放内存,并将临时变量(在您的程序中称为 root)设置为 NULL。 (顺便说一句,使用 nullptr 而不是 NULL。)但是如果你检查 P 的内容,它仍然是指 C 的释放地址。

      【讨论】:

      • 父级的哪一部分以及何时将其设置为 NULL(或 nullptr)?删除我的临时变量后?
      • 在我的示例中,您需要更改父节点的“左”字段。您的 deleteNode() 算法必须通过使用单独的临时变量来跟踪父级。并且需要知道你要删除的节点是父节点的左孩子还是右孩子。
      【解决方案3】:
      #include <iostream>
      using namespace std;
      
      template<typename T>
      class BinaryTree
      {
      private:
          struct Node
          {
              Node* parent = nullptr;
              Node* left = nullptr;
              Node* right = nullptr;
              T data{};
          };
          Node* root = nullptr;
      
      
      public:
          Node* get_root() const { return root; }
          const Node* search(const T& _data);
          void insert(const T& _data);
          T find_max(Node* node);
          T find_min(Node* node);
          Node* delete_node(Node* node,T& data);
          void print(Node* node);
      
      };
      
      
      template <typename T>
      const typename BinaryTree<T>::Node* BinaryTree<T>::search(const T& _data) 
      {
          Node* current = root;
      
          while (current)
          {
              if (current->data == _data)
              {
                  return current;
              }
              else if (current->data > _data)
              {
                  current = current->left;
              }
              else if (current->data < _data)
              {
                  current = current->right;
              }
          }
          return nullptr;
      }
      
      template <typename T>
      void BinaryTree<T>::insert(const T& _data)
      {
          Node* current = root;
      
          if (current == nullptr)
          {
              root = new Node;
              root->data = _data;
              return;
          }
      
          while (current)
          {
              if (current->data == _data)
              {
                  return;
              }
              if (_data > current->data)
              {
                  if (current->right == nullptr)
                  {
                      Node* newNode = new Node();
                      newNode->data = _data;
                      current->right = newNode;
                      newNode->parent = current;
                      return;
                  }
                  current = current->right;
              }
              else if (_data < current->data)
              {
                  if (current->left == nullptr)
                  {
                      Node* newNode = new Node();
                      newNode->data = _data;
                      current->left = newNode;
                      newNode->parent = current;
                      return;
                  }
                  current = current->left;
              }
          }
      }
      
      
      template <typename T>
      void BinaryTree<T>::print(Node* node)
      {
          if (node != nullptr)
          {
              print(node->left);
              std::cout << node->data << std::endl;
              print(node->right);
          }
      }
      
      //not used 
      template <typename T>
      T BinaryTree<T>::find_max(Node* node)
      {
          
          if (node->right != NULL)
          {
              find_max(node->right);
          }
          else {
              cout << node->data << std::endl;
          }
          return node->data;
      
      }
      
      template <typename T>
      T BinaryTree<T>::find_min(Node* node)
      {
          if (node->left != NULL)
          {
              find_max(node->left);
          }
          else {
              cout << node->data << std::endl;
          }
          return node->data;
      
      }
      
      template <typename T>
      
      typename BinaryTree<T>::Node* BinaryTree<T>::delete_node(Node* node, T& _data)
      {
          if (node == NULL) {
              return NULL;
          }
          else if (_data < node->data) {
              node->left = delete_node(node->left, _data);
          }
          else if (_data > node->data) {
              node->right = delete_node(node->right, _data);
          }
          else {
              if (node->left == NULL) {
                  Node* temp = node->right;
                  delete node;
                  return temp;
              }
              else if (node->right == NULL) {
                  Node* temp = node->left;
                  delete node;
                  return temp;
              }
              else {
                  node->data = find_min(node->right);
                  node->right = delete_node(node->right, node->data);
              }
          }
          return node;
      }
      
      
      
      
      int main()
      {
          BinaryTree<int> tree;
          int numb{};
      
          tree.insert(15);
          tree.insert(11);
          tree.insert(100);
          tree.insert(16);
          tree.insert(13);
          tree.insert(18);
          tree.insert(16);
          tree.insert(10);
      
          tree.print(tree.get_root());
          cout << endl << endl;
          cout << "Max: ";
          tree.find_max(tree.get_root());
          cout << endl << endl;
          cout << "Min: ";
          tree.find_min(tree.get_root());
          tree.print(tree.get_root());
          
          while (tree.search(numb)==nullptr) {
              cout << "Choose Number To Delete: ";
              cin >> numb;
          }
          
          cout << endl << endl;
          tree.delete_node(tree.get_root(), numb);
          tree.print(tree.get_root());
      
          return 0;
      }
      

      【讨论】:

      • 欢迎来到 StackOverflow!请避免编写纯代码答案:除了您的解决方案之外,请提供一些上下文。
      猜你喜欢
      • 1970-01-01
      • 2019-04-11
      • 1970-01-01
      • 2016-02-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多