您的位置:首页 > 其它

二叉搜索树——删除节点

2006-10-22 21:14 337 查看
前几天写了简单的二叉排序树的实现,仅仅提供了插入和查找操作,没有写删除给定节点操作。现在补充过来,不过这个代价似乎太大了点:)。二叉排序树的删除操作主要有两点要注意: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: