【问题标题】:Trouble in deleting root node in binary search tree在二叉搜索树中删除根节点的问题
【发布时间】:2013-07-06 23:07:48
【问题描述】:

我正在尝试从我的 BST 中删除根节点,然后打印树 inorder。根删除似乎是一个问题,所有其他节点都已成功删除。

根是 20。

按顺序打印 5 6 7 8 9 10 17 18 20 23 24 25 29 55 56 57 58 59

提供要删除的节点

20

删除后

5 6 7 8 9 10 17 18 20 5 6 7 8 9 10 17 18 23 24 25 29 55 56 57 58 59

正如您在删除后看到的那样,bintree 并不像预期的那样。粗体键是不需要的。 下面是我的代码

void treeDeleteNode (binTreeT **tree, binTreeT *node)
{
    binTreeT *succs;
    binTreeT *parent;
    binTreeT *root = *tree;

    if (node->rchild == NULL) {
        transplantTree (&root, node, node->lchild);
    }
    else if (node->lchild == NULL) {
        transplantTree (&root, node, node->rchild);
    }
    else {
        succs = treeMin (node->rchild);
        parent = getParentNode (root, succs);
        if (parent != node) {
            transplantTree (&root, succs, succs->rchild);
            succs->rchild = node->rchild;
        }
        transplantTree (&root, node, succs);
        succs->lchild = node->lchild;
    }
}


void transplantTree (binTreeT **root, binTreeT *old, binTreeT *new)
{
    binTreeT *rootRef = *root;
    binTreeT *parent;

    parent = getParentNode(rootRef, old);
    if (NULL == parent) {
        *root = new;
    }
    else {
        if (parent->lchild == old) {
            parent->lchild = new;
        }
        else {
            parent->rchild = new;
        }
    }
}


binTreeT* treeMin (binTreeT *tree)
{
    while (tree->lchild != NULL) {
        tree = tree->lchild;
    }
    return tree;
}


binTreeT* getParentNode(binTreeT *root, binTreeT* node)
{
    binTreeT *parent = NULL;

    while (root->data != node->data) {
        parent = root;
        if (node->data < root->data) {
            root = root->lchild;
        }
        else if(node->data > root->data) {
            root = root->rchild;
        }
    }
    return parent;
}


void inOrderPrint (binTreeT *tree)
{
    if (NULL != tree) {
        inOrderPrint (tree->lchild);
        printf("%d \t", tree->data);
        inOrderPrint (tree->rchild);
    }
}

.....任何帮助表示赞赏.....

【问题讨论】:

  • 你能解释一下你的算法吗?
  • 是的。函数“treeDeleteNode (binTreeT **tree, binTreeT *node)”将主 BST(树)和要删除的节点(节点)作为输入参数。如果要删除的节点有 2 个子节点,root=20 的情况下获取节点函数 treeMin 的后继,此时 succs=23 获取后继的父 getParentNode 输入 args 主树和后继 parent=20 如果后继的父是要删除的节点(successor has left child NULL) 用它的后继替换要删除的节点移植Tree(&root, node, succs)
  • contd: and make (succs key=23) succs->lchild = node->lchild .. 在这种情况下 node 是 root 并且 node->lchild is = 17 //下面的代码不会如果后继者的父节点不是要删除的节点,则在删除 root=20 时被命中然后 if (parent != node) { 用主树中的右子节点替换 (transplantTree) 使 succs-> 右子节点指向node->rchild(必须删除节点)现在替换(transplantTree)主树中要被后继删除的节点,并使succ-> lchild指向node-> lchild。

标签: c binary-search-tree


【解决方案1】:

在函数treeDeleteNode 中,每次调用transplantTree 函数时,都应该将tree 作为第一个参数而不是&amp;root 传递。这是因为根节点可以在这个函数中修改,这些修改应该是tree变量本身。

【讨论】:

  • 谢谢!你的评论让我意识到我的错误..在必要的地方将根更改为树,我的代码按预期工作..当然除了基本情况和我尚未实现的其他语义.. :-)跨度>
【解决方案2】:

改变

else {
    succs = treeMin (node->rchild);
    parent = getParentNode (root, succs);
    if (parent != node) {
        transplantTree (&root, succs, succs->rchild);
        succs->rchild = node->rchild;
    }
    transplantTree (&root, node, succs);
    succs->lchild = node->lchild;
}

else {
    succs = treeMin (node->rchild);
    parent = getParentNode (root, succs);
    if (parent != node) {
        //TODO:copy succs'content to node instead
        transplantTree (&root, succs, succs->rchild);
        free(succs);
    }
    else {
        transplantTree (&root, node, succs);
        succs->lchild = node->lchild;
        free(node);
    }
}

【讨论】:

  • 谢谢!但我不想实现复制内容的方法,而是在所有场景中都使用移植..发现我的代码的错误..
【解决方案3】:
void treeDeleteNode (binTreeT **tree, binTreeT *node)
{
    binTreeT *sub;

       //* find the place where node should be */
    while (*tree) {
        if (*tree == node) break;
        if ( node->data <= (*tree)->data) tree = &(*tree)->lchild;
        else tree = &(*tree)->rchild;
        }
        /* not found: nothing to do (except freeing node) */
    if ( !*tree) { free(node); return; }

        /* When we get here, *tree points to the pointer that points to node. 
        ** If any of the {l,r}pointers is NULL, the other
        ** will become the new root of the subtree (replacing node)
        */
    if ( !node->lchild) { *tree = node->rchild; free(node); return; }
    if ( !node->rchild) { *tree = node->lchild; free(node); return; }

        /* cut off left subchain of tree, save it, and set it to NULL */
    sub = node->lchild;
    node->lchild = NULL;


        /* find leftmost subtree of right subtree of 'node' */
    for (*tree = node->rchild; *tree; tree =  &(*tree)->lchild) {;}
        /* and put the remainder there */
    *tree = sub;

    free(node);
}

【讨论】:

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