【问题标题】:Removing a node with two children in a Binary Tree删除二叉树中具有两个子节点的节点
【发布时间】:2013-11-11 06:14:40
【问题描述】:

这就是我目前拥有的代码。我想我在很大程度上已经把逻辑搞砸了,但我被两个孩子困住了。我已经弄清楚我必须使用什么样的算法才能让它工作(我已经用 cmets 进行了注释在函数的底部),我只是不知道如何开始......谁能指出我正确的方向??

这是我目前所拥有的:

void BinaryTree::remove(int data){
// Is the data valid?
if(data < 0){
    cerr << data << " is not valid.  Must be a positive integer value."  << endl;
}
else{
    // Find the node
    BinNode* loc = root;
    BinNode* parent = nullptr;
    bool found = false;
    while(!found && loc != nullptr){
        if(data > loc->data){
            parent = loc;
            loc = loc->right;
        }
        else if(data < loc->data){
            parent = loc;
            loc = loc->left;
        }
        else found = true;
    }

    // If there is a parent, take care of the pointer
    if(parent != nullptr){
        if(loc->data < parent->data)
            parent->left = nullptr;
        else if(loc->data > parent->data)
            parent->right = nullptr;
    }
    // If there are children, save pointers to them
    BinNode* leftChild = nullptr;
    BinNode* rightChild = nullptr;  
    if(loc->left != nullptr)
        leftChild = loc->left;
    if(loc->right != nullptr)
        rightChild = loc->right;

    // So now pointers to the children have been saved (if they exist) and
    // parent pointers have been taken care of (if they exist) the node can be deleted
    // If no children exist simply just delete the node and return
    delete loc;
    // If one child exists
    if(leftChild != nullptr || rightChild != nullptr){  
        if(leftChild != nullptr){
            if(leftChild->data < parent->data)
                parent->left = leftChild;
            else if(leftChild->data > parent->data)
                parent->right = leftChild;
        }
        else if(rightChild != nullptr){
            if(rightChild->data < parent->data)
                parent->left = rightChild;
            else if(rightChild->data > parent->data)
                parent->right = rightChild;
        }       
    }

    // Both children exist...this sucks.
    else if(leftChild != nullptr && rightChild != nullptr){
        // Find a minimum in the right subtree
        BinNode * min = root;
        BinNode * minParent = nullptr;
        while(min->left != nullptr){
            minParent = min;
            min = min->left;
        }
        // Replace value of the node to be removed with the found minimum
        loc = new BinNode(min->data);

        // Delete the remaining duplicate node
        if(minParent != nullptr)
            minParent->left = nullptr;
        delete min;
    }
}
}

【问题讨论】:

  • 这是一个二叉搜索树 (en.wikipedia.org/wiki/Binary_search_tree),而不仅仅是二叉树。见en.wikipedia.org/wiki/Binary_search_tree#Deletion
  • 如何在正常的二叉树中执行删除操作?
  • 二叉树的结构比二叉搜索树少,因此您可以选择任何叶节点并将其交换到位。你问我,“如果我知道如何阅读一块刻有铭文的木头,我如何阅读一块木头?”答:随心所欲。
  • ....lol 好的,谢谢,让我删除我的整个功能...jk 我会弄清楚如何正确地为 BST 解决这个问题。
  • 二叉搜索树是一棵二叉树,它的元素保持一定的顺序。您的代码显示您正在使用二叉搜索树(因为您检查了顺序)。维基百科链接应该会有所帮助。

标签: c++ pointers binary-tree


【解决方案1】:

我们到了。这似乎有效。如果有人对我如何优化这个或我需要解决的问题有任何建议,请说出来!谢谢!

void BinaryTree::remove(int data){
// Is the data valid?
if(data < 0){
    cerr << data << " is not valid.  Must be a positive integer value."  << endl;
}
else{
    // Find the node
    BinNode* loc = root;
    BinNode* parent = nullptr;
    bool found = false;
    while(!found && loc != nullptr){
        if(data > loc->data){
            parent = loc;
            loc = loc->right;
        }
        else if(data < loc->data){
            parent = loc;
            loc = loc->left;
        }
        else found = true;

    // If there are children, save pointers to them
    BinNode* leftChild = nullptr;
    BinNode* rightChild = nullptr;  
    if(loc->left != nullptr)
        leftChild = loc->left;
    if(loc->right != nullptr)
        rightChild = loc->right;

    // So now pointers to the children have been saved (if they exist) and
    // parent pointers have been taken care of (if they exist) the node can be deleted
    // If no children exist simply just delete the node and return

    // Check if two children exist
    if(leftChild != nullptr && rightChild != nullptr){

        // Find a minimum in the right subtree
        BinNode * min = loc->right;
        BinNode * minParent = loc;
        while(min->left != nullptr){
            minParent = min;
            min = min->left;
        }
        // Replace value of the node to be removed with the found minimum
        loc->data = min->data;

        // Delete the duplicate
        if(minParent != loc)
            minParent->left = nullptr;
        else minParent->right = nullptr;
        delete min;
    }

    // If one child exists
    // Need to handle if it is the root here
    // change root pointer to remaining child
    else if(leftChild != nullptr || rightChild != nullptr){ 
        // If there is a parent, take care of the pointer
        if(parent != nullptr){
            if(loc->data < parent->data)
                parent->left = nullptr;
            else if(loc->data > parent->data)
                parent->right = nullptr;

        // Now loc can be deleted
        delete loc;
        if(leftChild != nullptr){
            if(parent != nullptr){
                if(leftChild->data < parent->data)
                    parent->left = leftChild;
                else if(leftChild->data > parent->data)
                    parent->right = leftChild;
            }
            // If it is the root
            else{
                root = leftChild;
            }
        }
        else if(rightChild != nullptr){
            if(parent != nullptr){
                if(rightChild->data < parent->data)
                    parent->left = rightChild;
                else if(rightChild->data > parent->data)
                parent->right = rightChild;
            }
            // If it is the root
            else{
                root = rightChild;
            }
        }       
    }

    // If there are no children
    else if (leftChild == nullptr && rightChild == nullptr){
        // If there is a parent, take care of the pointer
        if(parent != nullptr){
            if(loc->data < parent->data)
                parent->left = nullptr;
            else if(loc->data > parent->data)
                parent->right = nullptr;
        }
        // If it is the root
        else 
            root = nullptr;
        delete loc;
    }
}

【讨论】:

    猜你喜欢
    • 2012-01-07
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多