2012-02-17 16 views
1

私は大きなプロジェクトでは単純なバイナリ検索ツリーを作成しています。私はバイナリ検索ツリーの概念を理解しており、C++で実装する構文に問題があるだけです。私は意図的にブーストのツリーコンテナを使用していません。ツリーのコードは次のとおりです。ポインタでエラーが発生する

struct Tree{ 
int nodeValue; 
Tree *nodeChild1; 
Tree *nodeChild2; 
Tree(int userProvidedValue){ 
    nodeValue = userProvidedValue; 
    nodeChild1 = NULL; 
    nodeChild2 = NULL; 
} 
static void placeValue(Tree &parent, int value); 
static Tree findValue(Tree parent, int value); 
static void crawl(Tree parent); 
~Tree(){ 

    delete nodeChild1; 
    delete nodeChild2; 
} 
}; 

void Tree::placeValue(Tree &parent, int value){ 
Tree node = Tree(value); 
cout<<"made node"<<endl; 
if(value>parent.nodeValue){ 
    cout<<"eval node child 2"<<endl; 
    if(parent.nodeChild2 ==NULL){ 
     cout<<"reaching this"; 
     parent.nodeChild2 = &node; 
    } 
    else{ 
     placeValue(*parent.nodeChild2, value); 
    } 
} 
if(value<=parent.nodeValue){ 
    cout<<"eval node child 1"<<endl; 
    if(!parent.nodeChild1){ 
       cout<<"assigning"<<endl; 
       parent.nodeChild1 = &node; 
    } 
      else{ 
         placeValue(*parent.nodeChild1, value); 
      } 
     } 
} 

しかし、私はその後、Tree::placeValue(parent, 4)でそれを別のノードを追加するTree parent = Tree(5)でツリーを構築するたびにそれが正常にコンパイルされますが、メッセージは、exeファイルがクラッシュしたことを私に言ってポップアップ表示されます。

このクラッシュがどこから来ているのか理解してもらえますか?前もって感謝します。ツリーをクロールする

コードは次のようになります。

void Tree::crawl(Tree parent){ 
cout<<parent.nodeValue<<endl; 
if(NULL!=parent.nodeChild1){ 
    crawl(*parent.nodeChild1); 
} 
if(NULL!=parent.nodeChild2){ 
    crawl(*parent.nodeChild2); 
} 
} 

ボーナス質問:ツリー::クロールツリーの親の代わりに木&親の引数を取るとき、それは正常に動作します。ただし、&がないと失敗します。それはなぜそうだと誰も説明してもらえますか?

答えて

3

あなたはヒープ上にツリー(複数可)を割り当てる必要があります。

Tree node = Tree(value); 

ここでは、スタックにツリーを割り当てます。この変数のアドレスはスコープから外れた後に破棄されます。

Tree *node = new Tree(value); 

そして親の子として割り当てる::、ヒープ上にそれを割り当てるだけでnew演算子を使用するためには

parent.nodeChild2 = node; 

ツリー::クロールエラーについては、それがあります同じエラーに基づいています。スタックにはツリーを割り当てたままにしておき、スコープの外に出ると、そのデストラクタをdelete(ing)してnodeChild1とnodeChild2を呼び出します。関数を終了すると、ツリーのデストラクタが呼び出されないように、ポインタを使用するか、または常に参照を使用して、これらの種類の構造体を管理する必要があります。したがって:

void Tree::crawl(const Tree &parent){ 
    cout<<parent.nodeValue<<endl; 
    if(NULL!=parent.nodeChild1){ 
     crawl(*parent.nodeChild1); 
    } 
    if(NULL!=parent.nodeChild2){ 
     crawl(*parent.nodeChild2); 
    } 
} 

これはそれを行う必要があります。木の上に同じことを行うことを忘れないでください:: findValueは、あなたは、その機能のために、この署名を使用する必要があります。

static Tree findValue(const Tree &parent, int value); 
+0

ありがとうございます。しかし、今はTree :: crawlが呼び出されて同じことが起こると、プログラムがコンパイルされてクラッシュします。あなたは理由を考えることができますか? – jozefg

+0

Tree ::クロールコードを投稿しないと、私はあなたを助けることができません:D – mfontanini

+0

本当ですか?ごめんなさい!私はそれを投稿します。 – jozefg

3

新しい値を含むTree()インスタンスをスタックに割り当てます(Tree node = Tree(value);)。関数呼び出しが返ると、そのインスタンスは破棄されるので、後でアクセスしようとするとプログラムがクラッシュします。

また、あなたのデストラクタは、両方のその子にdeleteを呼び出すので、おそらくあなたの問題を解決するために、ヒープ上Treeインスタンスを割り当てる必要があります。Tree* node = new Tree(value);

+0

+1は 'new' /' delete'対称性のために+1します。 – David

+0

ありがとうございます、私はデストラクタを書いたと考えて、私はエラーをキャッチしたと思いますが、ああ。 – jozefg

0
Tree node = Tree(value); 

nodeは、それがで宣言されたプログラムブロックの範囲を持っているそれは自動的に終了した後deleledされます。 Tree::placeValueのうちポインタ(parent.nodeChild2 = &node;)を取得すると、終了後に何も指されず、逆参照しようとすると未定義の動作が発生します。これを動的に作成する:

Tree * node = new Tree(value); 
関連する問題