2016-10-14 16 views
-3

私はバイナリ検索ツリーを作成しようとしていますが、この消去機能は私にsegaultを与えます。私のNodeクラスには一時データがあり、親ノードとともに左の&右の子ノードへのポインタがあります。 私は、そのデータとしてキーを保持するノードにノード*を返す関数find(temp key)を持っています。だから私のメインの中で、私はこれでなぜseg fault(コアダンプ)が発生しますか?

Node<temp>* p = bTree->find(key); 

検索機能が動作していたが、その後、私は bTree->消去(p)を行うときに、 私の結果を印刷すると、私はコンパイルしますが、私はsegフォールトを取得します。助けてください、ありがとう。

template <typename temp> 
void BinTree<temp>::erase(Node<temp>* n){ 

    if(!n->lChild && !n->rChild){ //n has no children 
    delete n; 
    n = nullptr; 
    } 

    else if(n->lChild && n->rChild){ //n has two children 
    Node<temp>* p = n->rChild; 
    while(p->lChild) 
     p = p->lChild; //p will be n's successor 
    n->data = p->data; //set the data to that of the successor 
    if(p->rChild){ //take care of p's right child if it has one 
     p->parent->lChild = p->rChild; 
     p->rChild->parent = p->parent; 
    } 
    delete p; 
    p = nullptr; 
    } 

    else{ //n only has one child 
    if(n->parent){ 
     if(n->data < n->parent->data){ //n is a left child 
      if(n->lChild){ //n has only a left child 
       n->lChild->parent = n->parent; 
       n->parent->lChild = n->lChild; 
      } 
      else{ //n has only a right child 
       n->rChild->parent = n->parent; 
       n->parent->lChild = n->rChild; 
      } 
     } 
     else{ //n is a right child 
      if(n->lChild){ //n has only a left child 
       n->lChild->parent = n->parent; 
       n->parent->rChild = n->lChild; 
      } 
      else{ //n has only a right child 
       n->rChild->parent = n->parent; 
       n->parent->rChild = n->rChild; 
      } 
     } 
    } 
    else{ //n is the root and has no parent, but still only has one child 
     if(n->lChild) 
      root = n->lChild; 
     else 
      root = n->rChild; 
    } 
    delete n; 
    n = nullptr; 
    } 
} 
+0

プログラムをデバッグしましたか? –

+2

スタックオーバーフローへようこそ!デバッガを使用してコードをステップ実行する方法を学ぶ必要があるようです。良いデバッガを使用すると、プログラムを1行ずつ実行し、どこからずれているかを確認することができます。これはプログラミングをする場合に不可欠なツールです。詳しい読書:** [小さなプログラムをデバッグする方法](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/)** – NathanOliver

答えて

1

あなたはポインタについて深刻な誤解を受けています。

重要なことは、削除するノード自体だけでなく、他のポインタがノードを指していることです。

例えば、)(消去であなたの最初のケースを見てみましょう:

if(!n->lChild && !n->rChild){ //n has no children 
    delete n; 
    n = nullptr; 
} 

あなたはノードnを削除します。しかし、nの親はまだポインタを格納しています。

+0

nullptrを指していないでしょうか? – chuckj

+0

最後のコメントは気にしないでください。私はそれについても考えなかった。 – chuckj

+0

ポインタは、長い整数のような8バイトの数字です。 parent-> leftがノードのアドレスを格納し、別のポインタn = parent-> leftを設定すると、ノードの同じ8バイトのメモリアドレスが2つの場所に格納されます。 2番目の時刻は一時変数nに格納されます。ここで、 "nを削除する"とすると、変数nとparent-> leftに格納されている値は、まだ無効な古いアドレスであり、nullptrではありません。 –

関連する問題