二叉搜索树removeNode的实现

Implementation of removeNode for a Binary Search Tree

本文关键字:实现 removeNode 搜索树      更新时间:2023-10-16

我正在尝试在一个程序中实现一本教科书中讨论的二叉搜索树的删除算法,但是这本书对所描述的一些函数的细节很少,所以我已经猜到了它们的含义并实现了它指定的函数和我自己的一些函数。我遇到的问题是removeNode函数处理0-1-2个孩子的情况。

书中为removeNode指定了以下伪代码

removeNode(N: BinaryNode)
{
if(N is a leaf)
    Remove N from the tree
else if (N has only one child C)
{
    if(N was a left child of its parent P)
        Make C the left child of P
    else
        Make C the right child of P
}
else //Node has two children
{
    //Find S, the node that contains N's inorder successor
    //Copy the item from node S into node N
    //Remove S from the tree by using the previous
    //technique for a leaf or a node with one child
}

在这个函数中,如何使C成为p 的子元素?给定一个节点,没有指向父节点的任何东西你怎么做才能找出树的父节点是谁?通常你需要一个跟踪节点来跟踪,但由于书的"最终草案",我怀疑这不是他们所暗示的。

"最终稿"

removeNode(nodePtr: BinaryNodePointer): BinaryNodePointer
{
 if(N is a leaf)
 {
    //Remove leaf from the tree
    delete nodePtr
    nodePtr = nullPtr
    return nodePtr
 }
    else if (N has only one child C)
    {
        if(N was a left child of its parent P)
            nodeToConnectPtr = nodePtr->getleftChildPtr() //<---I assume this means nodePtr->left
        else
            nodeToConnectPtr = nodePtr->getRightChildPtr() //<--nodePtr->right?
        delete nodePtr
        nodePtr = nullptr
        return nodeToConnectPtr
    }
    else //Node has two children
    {
        //Find the inorder succesor of the entry in N: it is in the left subtree rooted
        //at N's Child
        tempPtr = removeLeftMosstNode(nodePtr->getRightChild(), newNodeValue)
        nodePtr->setRightChildPtr(tempPtr) //<--nodePtr->right = tempPtr?
        nodePtr->setItem(newNodeValue) // nodePtr->vendorData = newNodeValue?
        return nodePtr
    }

这是我基于上述设计提出的实现。我知道有些零件出了问题,但我不知道还能做些什么来修理它们。谁能建议解决儿童案件和任何其他问题,我可能错过了?

My Implementation

aBst::treeNode * aBst::removeNode(aBst::treeNode * nodePtr)
    {
        //This functions deletes a node and then returns the pointer to the child to take the place of deleted child
        aVendor * tempVendorPtr;
        treeNode * nodeToConnectPtr, *tempPtr;
        //The node passed is the node that needs to be removed
        if (nodePtr->right == NULL && nodePtr->left == NULL) //----No Child----
        {
            delete nodePtr;
            nodePtr = NULL;
            return nodePtr;
        }
        else if ((nodePtr->right != NULL) != (nodePtr->left != NULL))//----One Child----
        {
            if (nodePtr->left != NULL)//left child
            {
                nodeToConnectPtr = nodePtr->left; //Wrong
            }
            else if (nodePtr->right != NULL) //right child
            {
                nodeToConnectPtr = nodePtr->right; //Wrong
            }
            delete nodePtr;
            nodePtr = NULL;
            return nodeToConnectPtr;
        }
        else //-----Two Child-----
        {
            //find minimum value of right subtree, stores the pointer to the vendorData it carries through the parameter and calls removeNode
            tempPtr = removeLeftMostNode(nodePtr->right, tempVendorPtr);
            nodePtr->vendorData = tempVendorPtr;
            nodePtr->right = tempPtr;
            return nodePtr;
        }
    }

所有功能
int aBst::countKids(aBst::treeNode * subTreePtr)
{
    if (subTreePtr == NULL) //Empty Tree
    {
        return -1;
    }
    else if (subTreePtr->right == NULL && subTreePtr->left == NULL) //----No Child----
    {
        return 0;
    }
    else if ((subTreePtr->right != NULL) != (subTreePtr->left != NULL))//----One Child----
    {
        return 1;
    }
    else if ((subTreePtr->right != NULL) && (subTreePtr->left != NULL))//----Two Child----
    {
        return 2;
    }
    //Something unexpected occurred         
    return -1;
}
bool aBst::remove(char nameOfVendor[])
{
    bool failControl = false;
    removeValue(root, nameOfVendor, failControl);
    return failControl;
}
aBst::treeNode * aBst::removeValue(aBst::treeNode * subTreePtr, char nameOfVendor[], bool& success)
{
    //Note: the subTreePtr should be root in initial call
    treeNode * tmpPtr;
    char name[MAX_CHAR_LENGTH];
    //Make sure passed success bit is false
    success = false;
    subTreePtr->vendorData->getName(name);
    if (subTreePtr == NULL) //Empty Tree
    {
        success = false;
        return NULL;
    }
    else if (strcmp(name, nameOfVendor) == 0) //Evaluates to true if there is a match
    {
        subTreePtr = removeNode(subTreePtr);
        success = true;
        return subTreePtr;
    }
    else if (strcmp(name, nameOfVendor) > 0) // Go left
    {
        //Protects algorithm from bad data crash
        if (subTreePtr->left == NULL)
        {
            return subTreePtr;
        }
        tmpPtr = removeValue(subTreePtr->left, nameOfVendor, success);
        subTreePtr->left = tmpPtr;
        return subTreePtr;
    }
    else // Go Right
    {   
        //Protects algorithm from bad data crash
        if (subTreePtr->right == NULL)
        {
            return subTreePtr;
        }
        tmpPtr = removeValue(subTreePtr->right, nameOfVendor, success);
        subTreePtr->right = tmpPtr;
        return subTreePtr;
    }
    //For loop was broken and function returns false
    return subTreePtr;
}

aBst::treeNode * aBst::removeNode(aBst::treeNode * nodePtr)
{
    aVendor * tempVendorPtr;
    treeNode * nodeToConnectPtr, *tempPtr;
    //The node passed is the node that needs to be removed
    if (nodePtr->right == NULL && nodePtr->left == NULL) //----No Child----
    {
        delete nodePtr;
        nodePtr = NULL;
        return nodePtr;
    }
    else if ((nodePtr->right != NULL) != (nodePtr->left != NULL))//----One Child----
    {
        if (nodePtr->left != NULL)//left child
        {
            nodeToConnectPtr = nodePtr->left;
        }
        else if (nodePtr->right != NULL) //right child
        {
            nodeToConnectPtr = nodePtr->right;
        }
        delete nodePtr;
        cout << "calledn";
        nodePtr = NULL;
        return nodeToConnectPtr;
    }
    else //-----Two Child-----
    {
        //find minimum value of right subtree, stores the pointer to the vendorData it carries through the parameter and calls removeNode
        tempPtr = removeLeftMostNode(nodePtr->right, tempVendorPtr);
        nodePtr->vendorData = tempVendorPtr;
        nodePtr->right = tempPtr;
        cout << "nleaving Two Childn";
        return nodePtr;
    }
}
aBst::treeNode * aBst::removeLeftMostNode(aBst::treeNode * nodePtr, aVendor*& vendorDataRef)
{
    if (nodePtr->left == NULL)
    {
        //Target acquired
        vendorDataRef = nodePtr->vendorData;
        return removeNode(nodePtr);
    }
    else
        return removeLeftMostNode(nodePtr->left, vendorDataRef);
}

我想你和我有类似的问题。当只有一个子节点时,你所做的,就是分别将指针指向右或左分支。但是你需要用那个子树中的一个节点来替换这个节点。这可以通过在左子树中搜索最小节点并用这个最小节点替换您想要删除的节点来完成。然后需要删除刚刚插入的节点,以防止节点复制。这就是理论。我还没有设法实现正确的自己。

我又把链接删除了。我发现在回答问题时问问题被认为是不礼貌的。