尝试从二叉搜索树中删除节点时获取SEGFAULT

时间:2014-03-26 11:35:20

标签: c pointers memory-management tree

我在C中实现了一个二叉搜索树。下面的代码运行正常,只是当我尝试从树中删除一个子树时,我得到一个SEGFAULT:

源代码:

#include<stdlib.h>
#include<stdio.h>

struct node {
    int data;
    struct node * right, * left;
};

void insert(node ** tree, int val)
{
    node *temp = NULL;
    if(!(*tree))
    {
        temp = (node *)malloc(sizeof(node));
        temp->left = temp->right = NULL;
        temp->data = val;
        *tree = temp;
        return;
    }

    if(val < (*tree)->data)
    {
        insert(&(*tree)->left, val);
    }
    else if(val > (*tree)->data)
    {
        insert(&(*tree)->right, val);
    }

}

void print_preorder(node * tree)
{
    if (tree)
    {
        printf("%d\n",tree->data);
        print_preorder(tree->left);
        print_preorder(tree->right);
    }

}

void print_inorder(node * tree)
{
    if (tree)
    {
        print_inorder(tree->left);
        printf("%d\n",tree->data);
        print_inorder(tree->right);
    }
}

void print_postorder(node * tree)
{
    if (tree)
    {
        print_postorder(tree->left);
        print_postorder(tree->right);
        printf("%d\n",tree->data);
    }
}

 void deltree(struct node* node)
{
    if (node == NULL) return;

    struct node *r = node->right;

    deltree(node->left);
    free(node);
    deltree(r);
}

node* search(node ** tree, int val)
{
    if(!(*tree))
        return NULL;

    if(val < (*tree)->data)
    {
        return search(&((*tree)->left), val);
    }
    else if(val > (*tree)->data)
    {
        return search(&((*tree)->right), val);
    }
    else if(val == (*tree)->data)
    {
        return *tree;
    }
    return NULL;
}

void _deleteTree(struct node* node)
{
    if (node == NULL) return;

    _deleteTree(node->left);
    _deleteTree(node->right);

    printf("\nDeleting node: %d", node->data);
    free(node);
}

void deleteTree(struct node** node_ref)
{
  _deleteTree(*node_ref);
  *node_ref = NULL;
}


int  main()
{
    node *root;
    node *tmp;
    node *tmp1;

    root = NULL;
    insert(&root, 9);
    insert(&root, 4);
    insert(&root, 15);
    insert(&root, 6);
    insert(&root, 12);
    insert(&root, 17);
    insert(&root, 2);

    printf("\nPrinting tree before deletion...\n");
    print_postorder(root);

    tmp1 = search(&root, 15);

    printf("Deleting subtree...\n");
    deleteTree(&tmp1);

    printf("\nPrinting tree after deletion...\n");
    print_postorder(root);
}

输出:

Printing tree before deletion...
2
6
4
12
17
15
9

Deleting subtree...

Deleting node: 12
Deleting node: 17
Deleting node: 15
Printing tree after deletion...
2
6
4
Segmentation fault: 11

请注意,我想从整个树中删除子树(尽管我的代码也适用于整个树)。

2 个答案:

答案 0 :(得分:0)

当您使用参数deleteTree致电&tmp1时,deleteTree函数会将tmp1设置为NULL。但是,这对实际树中的相应指针(即树中指向包含值15的节点的节点的leftright指针没有影响。该指针仍然指向现在删除的节点。

按如下方式更改搜索:

node** search(node ** tree, int val)
{
    if(!(*tree))
        return NULL;

    if(val < (*tree)->data)
    {
        return search(&((*tree)->left), val);
    }
    else if(val > (*tree)->data)
    {
        return search(&((*tree)->right), val);
    }
    else if(val == (*tree)->data)
    {
        return tree;
    }
    return NULL;
}

主要功能如下:

node** tmp1;
...
printf("Deleting subtree...\n");
deleteTree(tmp1);

答案 1 :(得分:0)

你得到SEGFAULT的原因是你指的是一个毫无意义的地址。释放指向15的节点后,将tmp1设置为NULL。除非你没有将父对象的右子指针设置为NULL,否则你所做的一切都是正确的,现在它仍然指向原始地址。但是这个地址现在没有意义。在我的电脑上,它没有导致SEGFAULT,而是打印出一些随机数字。