【问题标题】:Segmentation Fault (Core dumped) in c BSTc BST 中的分段错误(核心转储)
【发布时间】:2014-07-08 11:11:29
【问题描述】:

这里我在二叉搜索树(BST)中做了一个删除程序,但在执行时出现分段错误(核心转储),我认为它在删除函数中,但不知道我是否删除了删除函数的函数调用那么它就可以正常工作了,例如查找最大元素,中序遍历,但删除不起作用。

#include<stdio.h>
#include<stdlib.h>
struct BST{
    int data;
    struct BST *left;
    struct BST *right;
};
struct BST *newNode(int data){
    struct BST *temp = (struct BST *)malloc(sizeof(struct BST));
    temp->data=data;
    temp->left=0;
    temp->right=0;
    return temp;
}
void inOrder(struct BST *root){
    if(root==0)
        return;
    inOrder(root->left);
    printf("%d",root->data);
    inOrder(root->right);
}
struct BST *findMax(struct BST *root){
    if(root==0)
        return 0;
    if(root->right!=0)
        return findMax(root->right);
    return root;
}
struct BST *dele(struct BST *root,int data){
    if(root==0)
        return 0;
    if(data<root->data)
        root->left=dele(root->left,data);
    if(data>root->data)
        root->right=dele(root->right,data);
    else{
        if(root->left && root->right)
        {
            struct BST *temp=findMax(root->left);
            root->data=temp->data;
            root->left=dele(root->left,root->data);
        }
        else{
            struct BST *temp=root;
            if(root->left==0)
                root=root->right;
            if(root->right==0)
                root=root->left;
            free(temp);
            return root;
        }
    }
    return root;
}
void main(){
    struct BST *root = (struct BST*)malloc(sizeof(struct BST));
    root=newNode(1);
    root->left=newNode(2);
    root->right=newNode(3);
    root->left->left= newNode(4);
    root->left->right=newNode(5);
    root->right->left=newNode(6);
    root->right->right=newNode(7);
    inOrder(root);
    root=dele(root,1);
    printf("\n\n");
    inOrder(root);
}

【问题讨论】:

  • 您是否尝试过使用调试器进行跟踪?
  • 我将删除重命名为删除,而不是同样的“分段错误”
  • @Joe 我无法调试,如果可以请帮忙。
  • @user1314485:为什么你“无法”调试?
  • 由于分段错误,我无法做任何事情,既不打印也不接受输入。但是现在问题已经解决了,但是感谢您的关注

标签: c segmentation-fault binary-search-tree


【解决方案1】:
void main(){

请改成:

int main(void) {

并使用NULL 而不是0 来比较指针

我的调试器告诉我:

程序收到信号SIGSEGV,分段错误。 0x00000000004007f0 在 demo.c:47 47 处删除(根 = 0x0,数据 = 5)
if(root->right==0)

调试步骤(使用 gdb):

  • 使用-g 标志编译:

    gcc -std=c99 -pedantic -Wall -Wextra -W -g -o demo demo.c

  • 启动 gdb:

    gdb 演示

  • 类型:

    运行

【讨论】:

  • @CoolGuy,对不起,您的编辑被拒绝,因为我正在编辑,请随时再次编辑
  • Bug 在 if(root->left==0) root=root->right;如果(根->右==0)根=根->左;但不是你所说的,这里的第二个“如果”应该是“否则如果”,但无论如何谢谢。
【解决方案2】:

罪魁祸首是

        if(root->left==0)
            root=root->right;
        if(root->right==0)
            root=root->left;

考虑leftright 分支都为NULL 的情况。然后第一个 if(测试left 是否为 NULL,即)将 NULL(right)分配给root。然后是下一个 if 并尝试取消引用 NULL 指针 (root-&gt;)。

我认为以下将纠正此错误

        if(root->left==0)
            root=root->right;
        else if(root->right==0)
            root=root->left;

或者:(已编辑:不,无论如何它都不会工作,因为新的right 可以不为 NULL

        if(root->left != NULL)
            root=root->left;
        if(root->right != NULL)
            root=root->right;

(注意在这种情况下leftright 不可能都是非NULL,因为这种情况之前已经处理过,所以这里没有内存泄漏)。

【讨论】:

  • 还是看不懂root-&gt;left=delete(root-&gt;left,root-&gt;data);这行(当root-&gt;left &amp;&amp; root-&gt;right
  • 别介意我之前的评论。现在我知道了。此外,我将编辑答案以注意我的第二个解决方案将不起作用。
【解决方案3】:

自己更正了,else部分删除功能有问题

else if(root->data==data){
        if(root->left && root->right)
        {
            struct BST *temp=findMax(root->left);
            root->data=temp->data;
            root->left=dele1(root->left,root->data);
        }
        else{
            struct BST *temp=root;
            if(root->left==0)
                root=root->right;
            else if(root->right==0)
                root=root->left;
            free(temp);
            return root;
        }
    }

我输入的节点值不代表 BST,而是代表二叉树。所以,也改了。

root=newNode(5);
    root->left=newNode(3);
    root->right=newNode(7);
    root->left->left= newNode(1);
    root->left->right=newNode(4);
    root->right->left=newNode(6);
    root->right->right=newNode(8);

分段错误被恢复

else if(root->right==0

而且,@Alter 我们可以同时使用 0 和 NULL,并且正如你所说的那样改变

if (root->left==0)
        root=root->right;
    if (root->right==0)
        root=root->left;

这是正确的,但我应该使用“else if”而不是第二个“if”。 不过感谢您对我的问题感兴趣。

【讨论】:

  • 感谢您的提示,+1
  • we can use both 0 as well as NUL,0 没有什么问题,但引用C-FAQ:任何使用 NULL(而不是 0)都应该被视为一个温和的提醒,即涉及到指针
猜你喜欢
  • 2020-12-31
  • 2019-08-11
  • 2022-01-14
  • 2017-02-25
  • 2016-07-12
  • 2018-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多