You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带双向迭代器的BST提取节点时假节点处理问题求助

解决BST假节点导致ExtractHelper出错的方案

你的问题核心在于假节点(对应end()的最右节点)不能被当作普通节点执行删除、值替换等操作,必须在ExtractHelper的关键逻辑点加入假节点判断,阻断对它的非法操作。以下是针对性的代码修改:

第一步:修改ExtractHelper入口判断

在函数开头先检查当前节点是否为假节点,直接返回避免后续逻辑错误:

node_type* ExtractHelper(node_type* root, Key key) {
    // 新增:遇到假节点直接返回,不处理
    if (root == nullptr || root->is_fake) {
        return root;
    }
    else if (key < root->value) {
        root->left = ExtractHelper(root->left, key);
    } else if (key > root->value) {
        root->right = ExtractHelper(root->right, key);
    } else {
        // 原逻辑修改部分见下文
    }
    return root;
}

第二步:处理目标节点的右子树(避免把假节点当普通右孩子)

当找到要删除的节点时,若它的右孩子是假节点,要当作right == nullptr处理——因为假节点不能被提升为有效子节点:

else {
    // 修改:判断右孩子是否为假节点,是的话视为空
    bool right_is_fake = (root->right != nullptr && root->right->is_fake);
    if (root->left == nullptr || right_is_fake) {
        node_type* temp = root->left; // 右是假节点,只保留左孩子
        DeleteNode(root);
        if (temp) {
            temp->parent = root->parent;
            // 维护父节点的子节点指针
            if (root->parent) {
                root->parent->left == root ? root->parent->left = temp : root->parent->right = temp;
            }
        } else if (root->parent) {
            // 无子节点时清空父节点对应指针
            root->parent->left == root ? root->parent->left = nullptr : root->parent->right = nullptr;
        }
        // 确保假节点始终挂在树的最右侧
        if (root->parent && right_is_fake) {
            node_type* new_rightmost = root->parent;
            while (new_rightmost->right && !new_rightmost->right->is_fake) {
                new_rightmost = new_rightmost->right;
            }
            new_rightmost->right = root->right;
            root->right->parent = new_rightmost;
        }
        return temp;
    } else if (root->right == nullptr) {
        // 左孩子处理逻辑,同步维护父节点指针
        node_type* temp = root->left;
        DeleteNode(root);
        if (temp) {
            temp->parent = root->parent;
            if (root->parent) {
                root->parent->left == root ? root->parent->left = temp : root->parent->right = temp;
            }
        } else if (root->parent) {
            root->parent->left == root ? root->parent->left = nullptr : root->parent->right = nullptr;
        }
        return temp;
    }
    // 修改:确保GetLeftest返回的不是假节点
    node_type* temp = GetLeftest(root->right);
    // 额外判断:如果temp是假节点,说明右子树只有假节点,按右为空处理
    if (temp->is_fake) {
        node_type* left_child = root->left;
        DeleteNode(root);
        if (left_child) {
            left_child->parent = root->parent;
            if (root->parent) {
                root->parent->left == root ? root->parent->left = left_child : root->parent->right = left_child;
            }
            // 重新挂载假节点到新的最右节点
            node_type* new_rightmost = left_child;
            while (new_rightmost->right && !new_rightmost->right->is_fake) {
                new_rightmost = new_rightmost->right;
            }
            new_rightmost->right = root->right;
            root->right->parent = new_rightmost;
        } else if (root->parent) {
            root->parent->right = root->right;
            root->right->parent = root->parent;
        }
        return left_child;
    }
    // 正常替换值并递归删除原节点
    root->value = temp->value;
    root->right = ExtractHelper(root->right, temp->value);
}

第三步:修改GetLeftest函数,避免返回假节点

GetLeftest需要在遍历左子树时,遇到假节点就停止,返回上一个有效节点:

node_type* GetLeftest(node_type* node) {
    if (node == nullptr || node->is_fake) {
        return nullptr;
    }
    while (node->left != nullptr && !node->left->is_fake) {
        node = node->left;
    }
    return node;
}

关键逻辑说明

  • 入口拦截:从根源避免假节点进入后续处理流程。
  • 右子树判断:将假节点视为“无效右孩子”,避免错误地将其提升为替代节点。
  • GetLeftest修正:保证找到的左最节点是有效数据节点,不会用假节点的值替换目标节点。
  • 假节点维护:删除节点后重新挂载假节点,确保迭代器的end()逻辑正常。

内容的提问来源于stack exchange,提问作者Rorik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 15:40:25