二叉搜索树——删除节点

前几天写了简单的二叉排序树的实现,仅仅提供了插入和查找操作,没有写删除给定节点操作。现在补充过来,不过这个代价似乎太大了点:)。二叉排序树的删除操作主要有两点要注意:1)必须修改的是删除节点父节点的信息;2)有四种情况需要考虑(删除节点有无左右子树的4个组合)。再加上一点就是要细心,考虑各种情况,例如根节点情况等。

实现源码为:

//main.cpp

///

//题目描述:删除给定二叉排序树的给定节点

//

//作者:k_eckel(韦福如)

//时间: 2005-09-30

//

 

#include <iostream>

using namespace std;

 

template <class T>

struct node

{

       node<T>* _lchild;

       node<T>* _rchild;

 

       T _key;

 

       node(const T& key):_lchild(NULL),_rchild(NULL),_key(key)

       {

       }

};

 

template <class T>

void Insert(node<T>*& root,const T& key)

{

       if (NULL == root)

       {

              node<T>* n = new node<T>(key);

              root = n;

              return ;

       }

 

       if (root->_key > key)

              Insert(root->_lchild,key);

       else

              Insert(root->_rchild,key);

}

 

template <class T>

void Delete(node<T>*& root,const T& key)

{

       if (NULL == root) return ;

 

       node<T>* prt = NULL;

       node<T>* crt = root;

 

       while ((NULL != crt) && (crt->_key != key))

       {

              prt = crt;

 

              if (crt->_key > key)

                     crt = crt->_lchild;

              else

                     crt = crt->_rchild;

       }

 

       //找不到待删除节点

       if (NULL == crt) return ;

 

       //待删除节点无左右节点

       //思想:修改当前节点父节点的左右(视当前节点是父节点的左右指针定)指针为NULL

       //注意处理根节点情况

       if ((NULL == crt->_lchild) && (NULL == crt->_rchild))

       {

              //为根节点,并且该根节点没有左右子树

              if (crt == root)

              {

                     root = NULL;

              }

              else //为叶子节点

              {

                     if (prt->_lchild == crt)

                            prt->_lchild = NULL;

                     else

                            prt->_rchild = NULL;

              }

       }

 

       //有左子树,没有右子树

       //思想:修改当前节点父节点的左右(视当前节点是父节点的左右指针定)指针指向当前节点左子树,

       //注意处理根节点情况

       if ((NULL != crt->_lchild) && (NULL == crt->_rchild))

       {

              if (crt == root)

              {

                     root = root->_lchild;

              }

              else

              {

                     if (crt == prt->_lchild)

                            prt->_lchild = crt->_lchild;

                     else

                            prt->_rchild = crt->_lchild;

              }

       }

 

       //有右子树,没有左子树

       //思想:修改当前节点父节点的左右(视当前节点是父节点的左右指针定)指针指向当前节点右子树,

       //注意处理根节点情况

       if ((NULL == crt->_lchild) && (NULL != crt->_rchild))

       {

              if (crt == root)

              {

                     root = root->_rchild;

              }

              else

              {

                     if (crt == prt->_lchild)

                            prt->_lchild = crt->_rchild;

                     else

                            prt->_rchild = crt->_rchild;

              }

       }

 

       //左右子树都存在,则将右子树最左端节点复制到待删除节点

       //思想:将右子树中最左的节点代替删除节点,注意处理根节点和右子树无左子树的情况

       if ((NULL != crt->_lchild) && (NULL != crt->_rchild))

       {

              node<T>* pre = crt->_rchild;

              while ((pre->_lchild != NULL) && (NULL != pre->_lchild->_lchild))

                     pre = pre->_lchild;

              node<T>* p = NULL;

              if (NULL != pre->_lchild)

              {

                     p = pre->_lchild;

                     pre->_lchild = NULL;

                    

                     p->_lchild = crt->_lchild;

                     p->_rchild = crt->_rchild;

                    

              }

              else

              {

                     p = pre;

                     p->_lchild = crt->_lchild;

              }

 

              if (crt == root)

              {

                     delete root;

                     root = p;

                     return ;

              }

             

              if (crt == prt->_lchild)

                     prt->_lchild = p;

              else

                     prt->_rchild = p;

       }

       delete crt;

}

 

template <class T>

void InorderPrint(const node<T>* root,const char* info)

{

       if (NULL == root) return ;

 

       if (info)

              cout<<info<<endl;

 

       if (NULL != root)

       {

              InorderPrint(root->_lchild,NULL);

              cout<<root->_key<<" ";

              InorderPrint(root->_rchild,NULL);

       }

 

}

 

int main(int argc,char* argv[])

{

       //测试代码

       node<int>* r = NULL;

       //建立一棵用于测试的排序二叉树

       Insert<int>(r,5);

       Insert(r,2);

       Insert(r,1);

       Insert(r,3);

       Insert(r,4);

       Insert(r,7);

       Insert(r,6);

       Insert(r,8);

       Insert(r,9);

 

       InorderPrint<int>(r,"before delete");

       cout<<endl;

 

       Delete<int>(r,25); //删除不存在的节点

       InorderPrint<int>(r,"after delete");

       cout<<endl;

 

      

       //Delete<int>(r,5); //有左右子树,根节点

       //Delete<int>(r,7); //有左右子树,非根节点

       //Delete<int>(r,1); //无左右节点

       //Delete<int>(r,8); //有右子树,无左子树

       //Delete<int>(r,8); //有右子树,无左子树

       Delete<int>(r,3);

       Delete<int>(r,4);

       Delete<int>(r,1);   //此时有左子树,无右子树

       InorderPrint<int>(r,"after delete");

       cout<<endl;

 

       Delete<int>(r,7);

       InorderPrint<int>(r,"after delete");

       cout<<endl;

 

       Delete<int>(r,9);

       Delete<int>(r,8);

       Delete<int>(r,2);

 

       InorderPrint<int>(r,"after delete");

       cout<<endl;

 

       Delete<int>(r,5);

       InorderPrint<int>(r,"after delete");

       cout<<endl;

 

       Delete<int>(r,6); //此时只有根节点,无左右子树

       InorderPrint<int>(r,"after delete");

       cout<<endl;

 

       return 0;

}

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值