【问题标题】:Stack overflow error while deleting BST node in C [closed]在C中删除BST节点时出现堆栈溢出错误[关闭]
【发布时间】:2017-10-02 03:01:53
【问题描述】:

我目前遇到了一个我似乎无法弄清楚的问题。目标是尝试从二叉搜索树中删除一个节点。出于某种原因,由于此功能,我一直遇到堆栈溢出。有什么我想念的吗?

int delete(struct node * n,int value) {
//if there is no bst 
if (n == NULL || head == NULL) {
    return 0;
}

//if head node is the node that has to be deleted
if (head->value == value) {
    if (head->left != NULL && head->right == NULL) {
        head = head->left;
    } else if (head->left == NULL && head->right != NULL) {
        head = head->right;
    } else if (head->left != NULL && head->right != NULL) {
        int temp = leftOfRight(head);
        head->value = temp;
        delete(head->right,temp);
    } else {
        head = NULL;
    }
}

if (n->left != NULL && n->left->value == value) { //if left node is the one that has to be deleted
    if (n->left->left != NULL && n->left->right != NULL) {
        int temp = leftOfRight(n->left);
        n->value = temp;
        delete(n->right,temp);
    } else if (n->left->left != NULL) {
        n->left = n->left->left;
    } else if (n->left->right != NULL) {
        n->right = n->right->right;
    } else {
        n->left = NULL;
    }
} else if (n->right != NULL && n->right->value == value) {
    if (n->right->left != NULL && n->right->right != NULL) { //if right node is that one that has to be deleted
        int temp = leftOfRight(n->right);
        n->value = temp;
        delete(n->right,temp);
    } else if (n->right->left != NULL) {
        n->right = n->right->left;
    } else if (n->right->right != NULL) {
        n->right = n->right->right;
    } else {
        n->right = NULL;
    }
} else if (value < n->value) {
    return delete(n->left,value);
} else if (value > n->value) {
    return delete(n->right,value);
}
return 1; }

【问题讨论】:

  • 你在上面放了调试器吗?在程序可靠失败的情况下,调试器始终是我的第一个工具。
  • head 变量从何而来?那是全球性的吗?
  • 您没有在 delete 中释放您的节点。因此,无论是 n->left 还是 n->right 它都指向某个实时内存位置但不是 null,因此条件可能始终为真并继续递归调用 delete 导致堆栈溢出。 LeftOfRight 功能代码也应该贴在这里:)
  • edit你的问题告诉我们你做了什么样的调试。我希望您已经在 Valgrind 或类似的检查器中运行了您的minimal reproducible example,并使用诸如 GDB 之类的调试器进行了调查。确保您也启用了全套编译器警告。这些工具告诉了你什么,它们缺少什么信息?并阅读 Eric Lippert 的 How to debug small programs

标签: c pointers binary-search-tree nodes


【解决方案1】:

主要问题是您在调用delete 后没有将指针设置为nullptr。这会导致未定义的行为。

让我演示一下:

//Create ptr & set to nullptr
Node* p_node = nullptr;
std::cout << "ptr: " << p_node << std::endl;

//Create new node on heap and point to it
Node* n = new Node(11);
p_node = n;
std::cout << "ptr: " << p_node << " node val: " << p_node->value << std::endl;

//Delete pointed-to object 
delete p_node;
std::cout << "ptr: " << p_node << " node val: " << p_node->value << std::endl;

//Set both ptrs back to nullptr
p_node = nullptr;
n = nullptr;
std::cout << "ptr: " << p_node << std::endl;

输出:

ptr: 0
ptr: 0x8c7de0 node val: 11
ptr: 0x8c7de0 node val: 3504064
ptr: 0

Delete 不会删除指针,而是调用指向对象的析构函数并释放内存。在此之后,我们将访问随机内存。

其他几点:

  • 很难了解整个上下文,但是您遍历树的方法似乎有点令人困惑。大多数 BST 实现使用带有 Node* current 的 while 循环,用于递归遍历列表,直到它到达要删除的值,或者变为 nullptr - while (current != nullptr) ... if (current-&gt;value == value) break; 然后检查节点是否有 0,1 或 2 个子节点- 并采取相应的行动。以这种方式阅读要简单得多。如果你想抽象它,你可以编写一个 find_node 函数,它只是将一个 ptr 返回到一个找到的节点。
  • Use nullptr 而不是 NULL。

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 1970-01-01
    • 2019-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多