删除BST中的节点

delete a node in BST

本文关键字:节点 BST 删除      更新时间:2023-10-16

我正在尝试实现BST的删除。我使用的算法是:

  1. 如果搜索匹配一个节点

1.1。如果剩下的子节点,请交换该节点的值及其左子节点。并再次调用左节点的功能。

1.2。否则,如果没有左节点,但是有右节点,请交换节点的值和右节点。调用右节点的功能。

1.3。如果没有左和右节点,请删除此节点。

以下是类定义。

class node{
  public:
  int value;
  node *left;
  node *right;
  node(){value=0; left=0; right =0;}
  node(int value){this -> value = value; left=0;right=0;}
  void print();
};
class tree{
  public:
  node *root;
  tree(){
    root = 0;
  }
  ~tree(){}
  void remove(node *, int);
  //tree(int value){root = &node(value);}
  void insert(int);
  void printSorted(node *);
  void printAll(node *);
};

print()函数要打印出我是...,我的左孩子是...,我的右孩子是...

void node::print(){
  if(this == 0) return;
  cout<<"i am "<<value<<endl;
  if(left !=0){
    cout<<"i have left, left is "<<left -> value<<endl;
  }
  if(right !=0){
    cout<<"i have right, right is "<<right -> value <<endl;
  }
}

printall()函数,从根和打印顺序遍历。

void tree::printAll(node *nodeP){
  if(nodeP == 0) return;
  else{
    node *iter = nodeP;
    if(iter -> left !=0){
      printAll(iter->left);
    }
    iter->print();
    cout<<endl;
    if(iter -> right !=0){
        printAll(iter -> right);
    }
  }
}

这是删除函数。

void tree::remove(node* origin, int toDel){
  if(origin == 0) return;
  node *orig_origin = origin;
  int tmp;
  if(origin -> value == toDel){
    if((origin -> left == 0) && (origin -> right == 0)){
      delete origin;
      origin =0;
    }
    else if((origin -> left != 0) && (origin -> right == 0)){
      tmp = origin -> value;
      origin -> value = origin -> left -> value;
      origin -> left -> value = tmp;
      remove(origin -> left, toDel);
    }
    else if((origin -> left == 0) && (origin -> right != 0)){
      tmp = origin -> value;
      origin -> value = origin -> right -> value;
      origin -> right -> value = tmp;
      remove(origin -> right, toDel);
    }
    else{ 
      tmp = origin -> value;
      origin -> value = origin -> left -> value;
      origin -> left -> value = tmp;
      remove(origin -> left, toDel);
    }
  }
  else{
    if(origin -> value > toDel) remove(origin -> left, toDel);
    else remove(origin -> right, toDel);
  }
  origin = orig_origin;
}

i输入7 4 10 1 6 5调用删除后,1处于原始4的位置。但是还有0。所以我以某种方式未能删除原始的1个节点。

sc-xterm-24:~/scratch/code/cpp_primer> ./a.out 
7 4 10 1 6 5 
i am 0
i am 1
i have left, left is 0
i have right, right is 6
i am 5
i am 6
i have left, left is 5
i am 7
i have left, left is 1
i have right, right is 10
i am 10

当您在树中找到值时,最后一个情况(左和右分支)的处理是错误的。您不能交换origin->valueorigin->left->value,因为这打破了树的订购所需的要求。由于原始origin->value大于左子树中存储的所有值,因此新的origin->left->value将大于origin->left->right子树中存储的所有值。由于节点中的值应少于存储在正确树中的所有内容,因此沿该分支的未来搜索可能会失败或找到错误的节点。