接着上一篇内容,继续实现二叉树节点的删除。结点的删除主要有两种方法,合并删除与复制删除。
合并删除的思想是先找到要删除的节点,如果要删除的节点同时有左右子树,则将左(或右)子树挂在要删除的节点的位置,之后将右(或左)子树挂在原来左(或右)子树的最右(或左)节点的右(或左)子树位置。
复制删除的思想是先找到要删除的节点,如果要删除的节点同时有左右子树,则进入到其左(或右)子树的最右(或左)节点,将该节点的内容复制到要删除的节点位置。之后若该节点仍有左(或右)子树(此时最多只会有一个子树,因为已经是最左或最右节点了),则将其子树挂在其父节点下面即可。然后该节点可以被删除。
C++代码如下:
头文件是上一节的扩充,增加了delete方法和判断节点状态(叶,单左右,全左右)方法。源文件中只列出了增加的方法。使用100*100000次的插入删除测试,程序运行正常,并且也没有内存泄露发生。
#ifndef _BIN_SEARCH_TREE_H_
#define _BIN_SEARCH_TREE_H_
#include "Constant.h"
template <class T>
class BinNode { public: BinNode(); BinNode(const T& data, BinNode<T> *l = NULL, BinNode<T> *r = NULL); bool isLeafNode(); bool isOnlyoneChildNode(bool &leftOrRight); T data; BinNode* left; BinNode* right; }; template <class T, unsigned int capacity> class BinSearchTree { public: BinSearchTree(); bool isEmpty(); bool isFull(); bool insert(T data); bool delViaMerge(T data); bool delViaCopy(T data); private: unsigned int treeNodeNum; BinNode<T> *root; }; #endif
C++源文件如下:
#include "BinSearchTree.h"
... ...
template<class T>
bool BinNode<T>::isLeafNode()
{
bool rs = false;
if ((NULL == left) && (NULL == right))
rs = true;
return rs;
}
template<class T>
bool BinNode<T>::isOnlyoneChildNode(bool &leftOrRight)
{
bool rs = false;
if ((NULL == left) && (NULL != right))
{
leftOrRight = true;
rs = true;
}
else if ((NULL != left) && (NULL == right))
{
leftOrRight = false;
rs = true;
}
else
{
rs = false;
}
return rs;
}
template<class T, unsigned int capacity>
bool BinSearchTree<T, capacity>::delViaMerge(T data)
{
bool rs = false;
if (isEmpty())
{
rs = false;
}
else
{
bool findOrNot = false;
BinNode<T> *preIter = NULL;
BinNode<T> *iter = root;
while (NULL != iter)
{
if (data < iter->data)
{
preIter = iter;
iter = iter->left;
}
else if(data > iter->data)
{
preIter = iter;
iter = iter->right;
}
else //find the node to del
{
findOrNot = true;
bool hasLeftOrRight = false;
if (iter->isLeafNode())
{
if (NULL != preIter)
{
if (preIter->left == iter)
{
delete iter;
iter = NULL;
preIter->left = NULL;
}
else
{
delete iter;
iter = NULL;
preIter->right = NULL;
}
}
else
{
delete iter;
iter = NULL;
root = NULL;
}
}
else if (iter->isOnlyoneChildNode(hasLeftOrRight))
{
BinNode<T> *needDeleteBuffer = iter;
if (hasLeftOrRight) //true means only right
{
iter = iter->right;
}
else //false means only left
{
iter = iter->left;
}
if (NULL == preIter)
{
root = iter;
}
else
{
if (preIter->left == needDeleteBuffer)
{
preIter->left = iter;
}
else
{
preIter->right = iter;
}
}
delete needDeleteBuffer;
needDeleteBuffer = NULL;
}
else //has both left and right child
{
BinNode<T> *needDeleteBuffer = iter;
iter = iter->left; //turn left
if (NULL == preIter)
{
root = iter;
}
else
{
if (preIter->left == needDeleteBuffer)
{
preIter->left = iter;
}
else
{
preIter->right = iter;
}
}
BinNode<T> *rightestNodeInLeftTree = NULL;
while (NULL != iter)
{
rightestNodeInLeftTree = iter;
iter = iter->right;
}
rightestNodeInLeftTree->right = needDeleteBuffer->right;
delete needDeleteBuffer;
needDeleteBuffer = NULL;
}
treeNodeNum--;
rs = true;
break;
}
}
if (false == findOrNot)
{
rs = false;
}
}
return rs;
}
template<class T, unsigned int capacity>
bool BinSearchTree<T, capacity>::delViaCopy(T data)
{
bool result = false;
if (isEmpty())
{
result = false;
}
else
{
bool findOrNot = false;
BinNode<T> *preIter = NULL;
BinNode<T> *iter = root;
while (NULL != iter)
{
if (data < iter->data)
{
preIter = iter;
iter = iter->left;
}
else if (data > iter->data)
{
preIter = iter;
iter = iter->right;
}
else //Find the node
{
findOrNot = true;
bool hasLeftOrRight = false;
if (iter->isLeafNode())
{
if (NULL != preIter)
{
if (preIter->left == iter)
{
delete iter;
iter = NULL;
preIter->left = NULL;
}
else
{
delete iter;
iter = NULL;
preIter->right = NULL;
}
}
else
{
delete iter;
iter = NULL;
root = NULL;
}
}
else if (iter->isOnlyoneChildNode(hasLeftOrRight))
{
BinNode<T> *needDeleteBuffer = iter;
if (hasLeftOrRight) //true means only right
{
iter = iter->right;
}
else //false means only left
{
iter = iter->left;
}
if (NULL == preIter)
{
root = iter;
}
else
{
if (preIter->left == needDeleteBuffer)
{
preIter->left = iter;
}
else
{
preIter->right = iter;
}
}
delete needDeleteBuffer;
needDeleteBuffer = NULL;
}
else //Copy delete
{
BinNode<T> *needConverNode = iter;
preIter = iter;
iter = iter->left; //turn left
while (NULL != iter->right)
{
preIter = iter;
iter = iter->right;
}
needConverNode->data = iter->data;
if (needConverNode == preIter)
{
preIter->left = iter->left;
}
else
{
preIter->right = iter->left;
}
delete iter;
iter = NULL;
}
treeNodeNum--;
result = true;
break;
}
}
if (false == findOrNot)
{
result = false;
}
}
return result;
}
测试代码如下:
BinSearchTree<int, 100000> binSearchTree;
int a[100000];
srand(time(0));
for (int i = 0; i < 100000; i++)
{ a[i] = rand(); }
for (int j = 0; j < 100; j++)
{ for (int i = 0; i < 100000; i++) { binSearchTree.insert(a[i]); }
for (int i = 0; i < 100000; i++)
{ if (i % 2 == 0) { binSearchTree.delViaCopy(a[i]); }
else
{ binSearchTree.delViaMerge(a[i]); }
}
}