使用复制问题删除原始二进制树(改进说明)

时间:2012-11-29 06:10:56

标签: c++ tree runtime binary-tree

我创建了Raw BinaryTree。在这棵树中,插入不像BST ,就像这样::

  1. 如果树是空的,那么添加值&让它成为根。 (假设30)
  2. 如果树不为空,则输入父值(30)&在其左子树中添加新值(20)。
  3. 如果左子树不为空,则将值(20)插入右子树。
  4. 对于下一次插入,再次使用父值来确定要添加的值的位置。 &安培;等...... ..
  5. 除非我尝试删除有两个孩子的节点,否则它的工作正常。我使用删除的方法是 deleteWithCopy

    正如我的导师所说,deletewithcopy是: 1.找到要删除的节点(temp)的父亲。 2.如果temp(要删除的节点)是'father'的右子,那么找到temp的直接后继者 3.如果temp(要删除的节点)是'father'的左子节点,那么找到temp的立即Predecessor 4.将temp的值与其前身/ succesor交换 5.删除temp(现在是树的叶子)。

    现在如何找到继承者&前身。

    Successor =节点的逻辑继承者是左子树中最右边的子节点

    Predecessor =节点的逻辑前驱是其右子树中最左边的子项

    根据算法,我创建了该函数,但删除后,当我遍历(或打印)树时,它显示运行时错误, binarytree.exe中0x008B5853处的未处理异常:0xC0000005:访问冲突读取位置0xFEEEFEEE。 这是“0xFEEEFEEE用于在Visual C ++中标记释放的内存”的错误。

    我再次干这个东西&再一次,在我试图访问的内存中没有任何超出限制,我已经修复了每个松散的结束,但仍然:(

    以下是功能:

    void BinaryTree<mytype>::deletewithTwoChild(BTNode<mytype> *temp)
    {
        BTNode<mytype> *father = findfather(temp, root);    //found address of father of temp node & stored it in pointer
        BTNode<mytype> *leaf = temp;    //created a copy of temp node
    
        /////CASE 1 (for predecessor)
    if(temp==root || father->left==temp)    //if temp is left child of its father then
    {
        leaf = leaf->left;  //move leaf 1 time left
        while(leaf->right!=0 )  //until leaf reaches the right most node of left subtree
        {
            leaf = leaf->right; //move leaf 1 time to right
        }
        //swapping values
        mytype var = leaf->key_value;   //created a template variable to store leaf's key
        leaf->key_value = temp->key_value;  //assigning temp's key to leaf
        temp->key_value = var;  //assigning leaf's key to temp
        if(leaf->right!=0)  //if leaf has right child then call deletewithOneChild function
        {
            deletewithOneChild(leaf);   //call to respective function
        }
        else if(leaf->left==0 && leaf->right==0) //if leaf has no children then
        {
            deleteWithNoChild(leaf);    //call to respective function
        }
    }
    /////CASE 2 (for successor)
    else if(father->right==temp)    //if temp is right child of its father, then
    {
        leaf = leaf->right; //move leaf 1 time right
        while(leaf->left!=0)    //until leaf reaches the last node of tree which has no child
        {
            leaf = leaf->left;  //move leaf 1 time to left
        }
        //swapping values
        mytype var = leaf->key_value;   //created a template variable to store leaf's key
        leaf->key_value = temp->key_value;  //assigning temp's key to leaf
        temp->key_value = var;  //assigning leaf's key to temp
        if(leaf->right!=0)  //if leaf has right child then call deletewithOneChild function
        {
            deletewithOneChild(leaf);   //call to respective function
        }
        else if(leaf->left==0 && leaf->right==0) //if leaf has no children then
        {
            deleteWithNoChild(leaf);    //call to respective function
        }
    }
    

    }

    数据集我正在使用:

                   30
                  /  \
                 20  80
                /   /  \
              10  40    120
                   \     / \ 
                  60  100 140
                  / \     /  \
                50  70   130 150
    

    我试图在弹出运行时错误时删除节点80,60,120,140。 Plz帮助:((我还需要指导如何删除树,如果删除了30。

1 个答案:

答案 0 :(得分:0)

据我所知,继任者和前任的定义是不同的。

后继者:右子树的最小节点,即右子树的最左侧节点。 Predecessor :左子树的最大节点,即左子树的最右边节点。

返回问题1 。在案例1中交换值后,我注意到if-else条件。因为,在案例1中,您找到子树的最右侧节点,leaf->right始终为null和{{1可能不是leaf->left。结果,在交换值之后不会调用删除函数。这将导致错误的BST问题,甚至更糟糕的是程序崩溃。因此,null条件将是:

if-else

第2期。据我所知,在BST中删除一个节点没有选择前驱或后继的规则,并且只有在交换整个节点而不是交换节点的值时才使用被删除节点的父(父)节点。因此,我的删除功能将是:

// leaf->right always be null, only need to verify leaf->left.
if (leaf->left != 0)
{
    deleteWithOneNode(leaf);
}
else 
{
    deleteWithNoChild(leaf);
}

通过使用该功能,删除30后的树将是

void BinaryTree<myType>::delete(BTNode<myType>* node, BTNode<myType>* parent)
{
    if (node->right) // find successor first
    {
        BTNode* ptrParent = node;
        BTNode* ptr = node->right;
        while (ptr->left)
        {
            ptrParnet = ptr;
            ptr = ptr->left;
        }

        // Since the ptr will be delete, we only assign the value of ptr to the value node
        node->key_value = ptr->key_value;

        if (node == ptrParent)
        {
            ptrParnet->right = ptr->right;
        }
        else
        {
            ptrParent->left = ptr->right;
        }
        delete ptr;            
    }
    else if (node->left) // find predecessor
    {
        BTNode* ptrParent = node;
        BTNode* ptr = node->left;
        while (ptr->right)
        {
            ptrParent = ptr;
            ptr = ptr->right;
        }

        // Since the ptr will be delete, we only assign the value of ptr to the value node
        node->key_value = ptr->key_value;

        if (node == ptrParent)
        {
            ptrParent->left = ptr->left;
        }
        else
        {
            ptrParent->right = ptr->left;
        }
        delete ptr; 
    }
    else
    {
        if (node->key_value > parent->key_value)
        {
            parent->right = NULL;
        }
        else
        {
            parent->left = NULL;
        }
        delete node;
    }
}