数据结构 ---- 搜索二叉树的基本操作(2)

实现非递归版本的搜索二叉树的插入、查找和删除

插入:这里的思想是定义两个指针一个指向当前结点,一个指向当前结点的父节点,当前结点就是找要插入的位置,插入整体分为两步,第一步是找到要插入的位置,第二步判断要插入的值与此时父节点的大小,来决定是插入到左子树还是右子树即可;
代码实现:

void SeachTreeInsert(SearchNode** pRoot ,SearchNodeType to_insert){
     if(pRoot == NULL){
         return;
     }
     if(*pRoot == NULL){
         SearchNode* new_node = CreateSearchNode(to_insert);
         *pRoot = new_node;
         return;
     }
     SearchNode* cur = *pRoot;
     SearchNode* pre = NULL;
     while(1){
         if(cur == NULL){
             //找到了插入的位置,跳出循环
             break;
         }
         if(to_insert < cur->data){
             pre = cur;
             cur =cur->lchild;
         }else if(to_insert > cur->data){
             pre = cur;
             cur = cur->rchild;
         }else{
             //相等的话,直接插入失败
             return;
         }
     }
     SearchNode* new_node = CreateSearchNode(to_insert);
     if(new_node->data < pre->data){
         pre->lchild = new_node;
     }else{
         pre->rchild = new_node;                                                                    
     }
     return;
 }

查找:直接循环去找,当要查找的值比根结点的值小时,往左子树找,大时往右子树找,相等时跳出循环找到了,跳出循环即可;
代码如下:

 SearchNode* SearchTreeFind(SearchNode* root,SearchNodeType to_find){
     if(root == NULL){
         return NULL;
     }
    SearchNode* cur = root;
     while(1){
         if(cur == NULL){
             break;
         }
         if(to_find < cur->data){
             cur = cur->lchild;                                                                     
         }else if(to_find > cur->data){
             cur = cur->rchild;
        }else{
             break;
         }
     }
     return cur;
 }

删除:这里的删除与递归版本的一样,先找到要删除的结点,然后分情况讨论:如果要删除的结点有孩子,就需要将孩子交付给父节点保管,不然删除结点之后他的孩子会被丢失;
代码实现:

 void SearchTreeRemove(SearchNode** pRoot,SearchNodeType to_remove){

    if(pRoot == NULL){
         return;
     }
     if(*pRoot == NULL){
         return;
     }
     SearchNode* to_remove_node = *pRoot;
     SearchNode* parent = NULL;
     while(1){
         if(to_remove_node == NULL){
             //没找到,要删除的元素,直接函数终止
             return;
         }
         if(to_remove < to_remove_node->data){
             parent = to_remove_node;
             to_remove_node = to_remove_node->lchild;
         }else if(to_remove > to_remove_node->data){
             parent = to_remove_node;
             to_remove_node = to_remove_node->rchild;
         }else {
             //找到了要删除的节点
             break;
         }
     }
     //2.如果找到了要删除的节点,分情况讨论
     if(to_remove_node->lchild == NULL && to_remove_node->rchild == NULL){
         //没有子树
         //此处我们要判断删除的节点是否是根结点
         if(to_remove_node == *pRoot){
             //要删除的元素是根结点
             *pRoot = NULL;                                                                         
         }else{
             //要删除的元素不是根结点
             //需要知道当前节点是parent的左子树还是右子树
             if(to_remove_node->data < parent->data){
                 parent->lchild = NULL;
             }else{
                 parent->rchild = NULL;
             }
         }
         //统一释放节点
         DestroySearchNode(to_remove_node);
         return;
     }else if(to_remove_node->lchild != NULL && to_remove_node->rchild ==NULL){
         //只有左子树
         if(to_remove_node == *pRoot){
             *pRoot = to_remove_node->lchild;
         }else{
             if(to_remove_node->data < parent->data){
                 parent->lchild = to_remove_node->lchild;
             }else{
                 parent->rchild = to_remove_node->lchild;                                           
             }
         }
         DestroySearchNode(to_remove_node);
         return;
     }else if(to_remove_node->lchild == NULL && to_remove_node->rchild != NULL){
         //只有右子树                                                                               
         if(to_remove_node == *pRoot){
             *pRoot = to_remove_node->rchild;
         }else{
             if(to_remove_node->data < parent->data){
                 parent->lchild = to_remove_node->rchild;
      }else if(to_remove_node->data > parent->data){
                 parent->rchild = to_remove_node->rchild;
             }
         }
         DestroySearchNode(to_remove_node);
         return;
     }else{
         //同时有左右子树
        SearchNode* min = to_remove_node->rchild;
       SearchNode* min_parent = to_remove_node;
        while(min->lchild != NULL){
            min_parent = min;
            min = min->lchild;
        }
        //循环结束之后,min就指向了to_remove_node右子树的最小值
        to_remove_node->data = min->data;
        if(min->data < min_parent->data){
            //min是min_parent的左子树
            //min一定没有左子树
            min_parent->lchild = min->rchild;
        }else{
            //通常情况下,min是min_parent左子树,
            //但是初始化情况下例外
            min_parent->rchild = min->rchild;
        }
     }
 }

猜你喜欢

转载自blog.csdn.net/liru_1996/article/details/80435749