C++模板实现二叉查找树(二 节点删除)

接着上一篇内容,继续实现二叉树节点的删除。结点的删除主要有两种方法,合并删除与复制删除。
合并删除的思想是先找到要删除的节点,如果要删除的节点同时有左右子树,则将左(或右)子树挂在要删除的节点的位置,之后将右(或左)子树挂在原来左(或右)子树的最右(或左)节点的右(或左)子树位置。

复制删除的思想是先找到要删除的节点,如果要删除的节点同时有左右子树,则进入到其左(或右)子树的最右(或左)节点,将该节点的内容复制到要删除的节点位置。之后若该节点仍有左(或右)子树(此时最多只会有一个子树,因为已经是最左或最右节点了),则将其子树挂在其父节点下面即可。然后该节点可以被删除。

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]);
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值