C++删除二进制树中的最小元素

C++ delete min element in binary tree

本文关键字:元素 删除 二进制 C++      更新时间:2023-10-16

我有以下删除最小元素的功能:

int BinaryTree::delete_min_helper(TreeNode *node){
   while(node->left != NULL){
     node = node->left;
   }
   if(node == root){
     return 1;
   }
   delete node;
   node = NULL;
   return 0;
}

我总是向这个函数传递一个指向根节点的指针。我试过这个和它的一些变体,但它似乎总是删除错误的东西,或者根本不删除任何东西。有什么想法吗?

下面是一个可编译的例子:

#ifndef _TREE_H_
#define _TREE_H_
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct TreeNode {
  int val;
  char *str;
  TreeNode *left;
  TreeNode *right;
};
class BinaryTree {
  public:
 BinaryTree();
 ~BinaryTree();
 int insert_node(unsigned int val, char *str);
 TreeNode *find_min();
 int delete_min();
 void print();
 private:
 int insert_node_helper(TreeNode *&node, unsigned int val, char *str);
 int delete_min_helper(TreeNode *node);
 void print_helper(TreeNode *node);
 TreeNode *root;  
};
#endif
BinaryTree::BinaryTree(){
  this->root = NULL;
}

BinaryTree::~BinaryTree(){
}
int BinaryTree::insert_node(unsigned int val, char *str){
  return insert_node_helper(this->root, val, str);
}
int BinaryTree::insert_node_helper(TreeNode *&node, unsigned int val, char *str){
  if(node == NULL){
    node = new TreeNode;
    node->val = val;
    node->str = strdup(str);
    node->left = NULL;
    node->right = NULL;
    if(node != NULL){
      return 0;
    }else{
      puts("inserted null node");
      return 1;
   }
 }else if(val <= node->val){
   return insert_node_helper(node->left, val, str);
 }else if(val > node->val){
   return insert_node_helper(node->right, val, str);
 }
 return 1;
}
void BinaryTree::print(){
  print_helper(this->root);
}

void BinaryTree::print_helper(TreeNode *node){
    if(node != NULL){
      print_helper(node->right);
      printf("%d occurrences of "%s"n", node->val, node->str);
      print_helper(node->left);
    }
}
TreeNode *BinaryTree::find_min(){
  TreeNode *temp = this->root;
  while(temp->left != NULL){
    temp = temp->left;
  }
  return temp;
}
int BinaryTree::delete_min(){
   return delete_min_helper(root);
}
int BinaryTree::delete_min_helper(TreeNode *node){
   while(node->left != NULL){
     node = node->left;
   }
  if(node == root){
    puts("attempted to delete root");
    return 1;
  }
  delete node;
  node = NULL;
  return 0;
}
#include <time.h>
int main(){
  BinaryTree bt;
  srand(time(NULL));
  for(int i = 0; i < 10; i++){
     bt.insert_node(rand() % 20, "test");
  }
  bt.print();
  printf("min val = %dn", bt.find_min()->val);
  puts("#################################");
  bt.delete_min();
  bt.print();
  printf("min val = %dn", bt.find_min()->val);
  return 0;
}

您将引用指针作为参数(TreeNode *&node),然后对其进行修改。因此,如果将树的根传递给此方法,则最终会将根设置为NULL

此外,这实际上完全不删除任何内容,因为您在将指针设置为NULL后调用delete,而对NULL指针调用的delete则不执行任何操作。

编辑原始帖子后更新:

我假设root是BinaryTree的成员。如果你发布一个简短的、自给自足的、可编译的例子,会更容易帮助你。

你仍在扎根作为参考。因此,node == root永远是真的,你永远不会达到你的delete语句。所以实际上你并没有删除任何内容,而是将根节点更改为最左边的子节点。

尝试将方法签名更改为

int BinaryTree::delete_min_helper(TreeNode *node){

即没有安培数(&)。

编辑后:

好的,现在我已经运行了你的程序,发现了你的第二个问题。在线

node = NULL;

您正在更改本地指针的值,而不是父节点中left指针的值。这意味着,下次遍历树时,您将访问一个指向刚刚删除的内存的指针。这会引发未定义的行为。为了避免这种情况,您应该在删除叶节点时将父节点的left-指针设置为0。