删除BST中的节点

时间:2017-09-08 21:16:38

标签: c++ binary-search-tree

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

  1. 如果搜索匹配一个节点
  2. 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;
    }
    

    我输入7 4 10 1 6 5 在调用delete之后,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
    

1 个答案:

答案 0 :(得分:0)

当您在树中找到值时,处理最后一个案例(左右分支都存在)是错误的。您无法交换origin->valueorigin->left->value,因为这会破坏树所需的排序。由于原始origin->value大于存储在左子树中的所有值,因此新origin->left->value将大于origin->left->right子树中存储的所有值。由于节点中的值应该小于存储在右侧树中的所有内容,因此将来对该分支的搜索可能会失败或找到错误的节点。