2016-10-18 27 views
1

私は、エクササイズのようにCで単純なバイナリ検索ツリーを実装しようとしています。私はツリーに要素を挿入することができますが、特定の点では(私はどこに分かれているのか分かりませんでした)、私はセグメンテーションフォルトを得ています。ここでCセグメンテーションフォールトのバイナリ検索ツリー

が私のコードです:再帰呼び出しが戻ったときにこの質問を書いている時点で

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

struct node { 
    struct node *left; 
    struct node *right; 
    int key; 
}; 

void insert(struct node *treeNode, int key); 
void outputTree(struct node *root); 

int main(){ 
    //Store how many numbers the user will enter 
    printf("How many numbers will you enter? > "); 
    int numNumbers; 
    scanf("%d", &numNumbers); 

    //Create a root node 
    struct node root; 
    root.key = -1; //-1 Means the root node has not yet been set 
    root.right = NULL; 
    root.left = NULL; 

    //Now iterate numNumbers times 
    int i; 
    for(i = 1; i <= numNumbers; ++i){ 
     int input; 
     scanf("%d", &input); 
     insert(&root, input); 
    } 

    outputTree(&root); 

    return 0; 
} 

void insert(struct node *treeNode, int key){ 
    //First check if the node is the root node 
    if((*treeNode).key == -1){ 
     printf("Root node is not set\n"); 
     (*treeNode).key = key; //If the root node hasn't been initialised 
    } 
    else { 
     //Create a child node containing the key 
     struct node childNode; 
     childNode.key = key; 
     childNode.left = NULL; 
     childNode.right = NULL; 

     //If less than, go to the left, otherwise go right 
     if(key < (*treeNode).key){ 
      if((*treeNode).left != NULL){ 
       printf("Left node is not null, traversing\n"); 
       insert((*treeNode).left, key); 
      } 
      else { 
       printf("Left node is null, creating new child\n"); 
       (*treeNode).left = &childNode; 
      } 
     } 
     else { 
      //Check if right child is null 
      if((*treeNode).right != NULL){ 
       printf("Right node is not null, traversing...\n"); 
       insert((*treeNode).right, key); 
      } 
      else { 
       printf("Right node is null, creating new child\n"); 
       (*treeNode).right = &childNode; 
      } 
     } 
    } 
} 

void outputTree(struct node *root){ 
    //Traverse left 
    if((*root).left != NULL){ 
     outputTree((*root).left); 
    } 
    printf("%d\n", (*root).key); 
    if((*root).right != NULL){ 
     outputTree((*root).right); 
    } 
} 

、私は考えを持っていた、子供が参照で、スタック上に作成され、その中のノードですツリーはもはや存在しない構造体を指していますか?

ここで何が間違っていますか?

ありがとう

+1

を使用するだけでルートを作成します。ここに投稿する前にそれを行う必要があります。 –

+0

Re: "この質問を書いている時点では、子ノードがスタック上に作成されているので、再帰呼び出しが返ってくると、ツリーの参照はもはや存在しない構造体を指していますか? "それはまさに正しいことです! – ruakh

+3

スタック上に 'childNode'を作成していますが、関数が終了すると無効になります。 'malloc'などを使うべきです。 – mch

答えて

1

静的割り当てによってスタックに子ノードを作成します。挿入メソッドが終了すると、子参照は無効になります。 mallocで動的割り当てを使用する必要があります。

struct node *new_node(int key, struct node *left, struct node *right) { 
    struct node *this = malloc(sizeof *this); 
    this->key = key; 
    this->left = left; 
    this->right = right; 
    return this; 
} 

無料機能ですべての割り当てを無料にすることを忘れないでください。

編集: ので、デバッガでコードをステップ実行するとき、あなたはラインがセグメンテーションフォールトを引き起こした、まさに決定することができるはずです

struct node *root = new_node(-1, NULL, NULL); 
関連する問題