2016-11-13 1 views
0

配列の数値のリストを調べ、バイナリ検索ツリーに挿入する小さなプログラムを作成しようとしています。ここで私が持っているものです。初期化されていない値を関数に解析する

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

typedef struct node_t node_t; 

struct node_t { 
    int data; 
    node_t *left; 
    node_t *right; 
}; 

int insert(node_t *node, int n); 

int main(void) { 
    int array[8] = {5, 8, 3, 6, 9, 2, 4, 7}; 
    int i; 
    node_t *root; 

    for (i = 0; i < 8; i++) { 
     insert(root, array[i]); 
    } 

    return 0; 
} 

int insert(node_t *node, int n) { 

    if (node == NULL) { 
     node = malloc(sizeof node); 
     node->data = n; 
     return 1; 
    } 

    if (n > node->data) { 
     insert(node->left, n); 

    } else if (n < node->data) { 
     insert(node->right, n); 

    } else { 
     return -1; 
    } 

    return 0; // Suppress 'control reaches end of non-void function' 
} 

私はgccでコンパイルしたとき、私は言って警告を取得「『ルート』を、この関数で初期化されていない使用することができます」。それは(少なくとも、Windows上の)エラーになり実行されている、しかし、main()root->dataをプリントアウトして得た入力ノードへのポインタは、それがNULLだった場合、私が実装しようとしていたアイデアはinsert()機能をチェックしていた0

それをmallocできます。また、再帰がどのように処理されるかによって、挿入される数はそのノードに挿入される必要があります。ノードがNULLと等しくない場合は、番号を挿入するノードの側で再帰的にinsert()を呼び出します。

これは、ポインタと何か関係がある理由を理解していますrootどこにも指向されていないか、root->left/root->right、しかし、私はこれを修正するために何ができるかわかりません。どんな助けもありがとう、ありがとう!

+0

再帰呼び出しの戻り値はどうなりますか? –

+1

あなたの問題については、c *で参照によってエミュレートするパスを検索してください。 –

+0

@Someprogrammerdude申し訳ありませんが、問題のトラブルシューティングを試みている間違った場所からコードを取得したため、いくつか編集しました。検索が行われる限り、私は何かが不足している可能性がありますが、Googleの上位3つの結果は役に立たなかったようです。初期化された変数のアドレスを関数に渡しているのに対し、ポインタを渡しているようです何を保管すべきかを知らされていない住所。 – Arkantos

答えて

1

投稿したコードにさらに問題があるかもしれませんが、私は以下のいくつかの問題を挙げました。

それはあなたのためにメモリを割り当てる必要があるノードであるので、それはNULLが含まれている場合は、この変更する必要があります。これに

if (node->data == NULL) { 

if (node == NULL) { 

をまた、あなたが開始する必要がその時点で何が起こっていても、それはNULLになっているかもしれないし、そうでないかもしれないからです(挿入機能で比較したいものです)。だから、それはそうのように開始:

node_t *root = NULL; 

最終のものは機能のcalloc(または別々にメモリ上のゼロにはmemsetを行う)するのmallocに変更することです。それ以外の場合、変数node-> leftおよびnode-> rightには、NULL以外の値が含まれていて、初期化されていないメモリを使用する可能性があります。

+0

フィードバックをいただきありがとうございます、ええ、あなたが私が投稿した直前に最初のことを見つけました。私は今あなたが言った2つの事を変更しました、そして、確かにそれはどんな誤りも返しません。しかし、私がforループの後でmainに入って 'printf("%d \ n "、root-> data);を実行しようとすると、プログラムはエラーメッセージなしでクラッシュします。何が起こっているのか知っていますか? – Arkantos

+0

関数内のメモリを変更するには、アドレスをメモリに渡す必要があることに注意してください。つまり、ダブルポインタを使用する必要があります。そうしないと、挿入関数は役に立たなくなります。 – staringlizard

1

あなたのプログラムは実際に関数に変数unintialized rootを渡しません。しかし、rootを初期化しても、まだツリーにデータを入れるために、ポインタ(ポインタ(root)をmain()内で変更できるようにする必要があるため) が問題になります。同様に、引数を に変更して、への再帰呼び出しも変更する必要があります。

実際には戻り値insert()を使用していないことがわかりました。だから、それはちょうどvoid機能かもしれません。いくつかの問題を説明するコード内のコメントを追加しました。

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

typedef struct node_t node_t; 

struct node_t { 
    int data; 
    node_t *left; 
    node_t *right; 
}; 

void print(node_t *r) { /* In order tree traversal. Gives the sorted output. */ 
    if (!r) return; 
    print(r->left); 
    printf("%d ", r->data); 
    print(r->right); 
} 

void insert(node_t **node, int n); 

int main(void) { 
    int array[] = {5, 8, 3, 6, 9, 2, 4, 7};  /* Removed the size. It can be calculated using sizeof and helps when array size changes */ 
    int i; 
    node_t *root = NULL; 

    /* Without hard-coding, array size can be calculated like this. */ 
    for (i = 0; i < sizeof array/sizeof array[0]; i++) { 
     insert(&root, array[i]); 
    } 

    print(root); 
    return 0; 
} 

void insert(node_t **node, int n) { 
    if (*node == NULL) { 
     *node = malloc(sizeof *node); 
    if (*node == NULL) { /* Need to check the return value for failure. */ 
      perror("malloc"); 
      exit(1); 
     } 
    (*node)->left = (*node)->right = NULL; 
     (*node)->data = n; 
    return; 
    } 

    if (n < (*node)->data) /* Insert smaller elements on the left for it to be a binary tree - but not neccessary */ 
     insert(&(*node)->left, n); 
    else /* Another else below this isn't needed. There can't be any error with the number 'n' itself */ 
     insert(&(*node)->right, n); 
} 
+0

返信いただきありがとうございます!私はあなたのプログラムを実行しようとしたが、それはうまくコンパイルされますが、私はそれがエラーメッセージ(私はWindows上で)なしでクラッシュします。限りポインタのものへのポインタまで、それをクリアするためのおかげで!私が先に探検したとき、それは私が出くわした方法でしたが、それはあまりにも面倒だったようですが、結局のところそうです。いずれにしても、クラッシュについて何かできることはありますか? – Arkantos

+0

@Arkantos既存のプログラムを修正しましたか?私が投稿したコードには何の問題もありません。おそらく、私の提案でプログラムを修正しようとしましたが、いくつか見逃してしまいました( 'node_t * root = NULL;'など)?いずれの場合でも、デバッガを実行して、クラッシュの原因となっているコード行を見つけることができます。 –

関連する問題