二叉树实现在C中给出了分段错误

时间:2016-10-27 14:04:09

标签: c pointers struct segmentation-fault binary-tree

我在尝试访问存储在TreeNode中的数据时遇到了分段错误。这是代码:

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

typedef struct NodeTag{
    int value;
    struct NodeTag *LLink;
    struct NodeTag *RLink;
} TreeNode;

void inOrder(TreeNode * n){
    if(n->LLink != NULL)
        inOrder(n->LLink);
    printf("%d ", n->value);
    if(n->RLink != NULL)
        inOrder(n->RLink);
}

void newNode(TreeNode * n, int v){
    n = malloc(sizeof(TreeNode));
    n->value = v;
    n->LLink = NULL;
    n->RLink = NULL;
}

void addValue(TreeNode * r, int value){

    if(value < r->value){
        if(r->LLink == NULL){
            newNode(r->LLink, value);
        } else {
            addValue(r->LLink, value);
        }
    } else if (value > r->value) {
        if(r->RLink == NULL){
            newNode(r->RLink, value);
        } else {
            addValue(r->RLink, value);
        }
    }
}



int main(){

    TreeNode * root = 0;
    newNode(root, 1);
    printf("%d\n", root->value); //<--This is where I get the fault
    //addValue(root, 3);
    //addValue(root, 10);
    //addValue(root, 2);

    //inOrder(root);

    return 0;
}

如果有人能向我解释为什么我会收到此错误,我们将不胜感激。我是一名学习C的学生,而且我对指针等不太熟悉。

3 个答案:

答案 0 :(得分:2)

void newNode(TreeNode * n, int v){
    n = malloc(sizeof(TreeNode));
    n->value = v;
    n->LLink = NULL;
    n->RLink = NULL;
}

在此代码中,n是指向TreeNode结构的指针,但如果您为n指定了某些内容,则在函数外部不会看到这一点,因为指针是按值传递的

void writeToA ( int a ) {
    a = 5;
}

int main ( ) {
    int x = 10;
    writeToA(x)
    printf("%d\n", x);
}

此代码会打印什么?它将打印10,而不是5。那是因为x的值传递给函数,而不是x的引用。在函数中更改该值不会更改函数外的x值。

指针也是一个值,基本上它是一个int,而int值是一个内存地址:

void writeToPtr1 ( int * a ) {
    int i = 10;
    a = &i; // `a` now points to the memory address of i
}

void writeToPtr2 ( int * a ) {
    *a = 5; // This doesn't change where `a` points to,
    // it writes 5 to the memory address to that `a` points to.   
}

int main ( ) {
    int x = 10;
    int *ptr = &x; // ptr now points to the memory address of x!
    writeToPtr1(ptr);
    // ptr still points to the memory address of x!
    // As not a reference to ptr was passed, the memory
    // address of x was passed to the function!

    writeToPtr2(ptr);
    // ptr still points to the memory address of x!
    // But this memory now has the value 5 and not 10 anymore.
}

您需要返回分配结果:

TreeNode * newNode ( int v ) {
    TreeNode * n = malloc(sizeof(TreeNode));
    n->value = v;
    n->LLink = NULL;
    n->RLink = NULL;
    return n;
}

int main ( ) {
    TreeNode * root = newNode(1);
    printf("%d\n", root->value);
    return 0;
}

或者您需要传递对指针的引用,然后更改指针指向的值:

 void newNode ( TreeNode ** outNode, int v ) {
    // TreeNode ** is a pointer to a pointer to a TreeNode!
    TreeNode * n = malloc(sizeof(TreeNode));
    n->value = v;
    n->LLink = NULL;
    n->RLink = NULL;
    *outNode = n; // Make the pointer point to `n`
}

int main ( ) {
    TreeNode * root = NULL;
    newNode(&root, 1); // Pass a pointer to root
    printf("%d\n", root->value);
    return 0;
}

答案 1 :(得分:0)

newNode要么返回指向已分配内存的指针,要么可以向该函数发送双指针并在那里分配内存。

TreeNode* newNode(int v){
    TreeNode *new_node = malloc(sizeof(TreeNode));

    n->value = v;
    n->LLink = NULL;
    n->RLink = NULL;

    return new_node
}

void newNode(TreeNode ** n, int v){
    *n = malloc(sizeof(TreeNode));
    (*n)->value = v;
    (*n)->LLink = NULL;
    (*n)->RLink = NULL;
}

答案 2 :(得分:0)

在C中,参数按值传递。因此,调用newNode(r->LLink, value)不会修改r->LLink

考虑这个简单的功能:

void Foo(int x)
{
  x = x * 2 ;
}

调用Foo(n)会将n乘以2吗?否。

你要么需要这个:

void Foo(int *x)
{
  *x = *x * 2 ;
}

并致电Foo(&n);

或:

void Foo(int x)
{
  return x * 2 ;
}

并致电n = Foo(n);