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]); }
        }
    }
    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/luanzheng_365/article/details/68173833
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞