2016-11-21 5 views
0

バイナリ検索ツリーポインタに問題があり、その原因を特定できません。私は2本の木をとり、木の2つのサブツリーを所定の位置に交換する機能を持っています。これが交換を行うコードです。C++ツリーポインタの問題

opNode* tmp = new opNode(); 
opNode* tmp2 = new opNode(); 
tmp = this->clone(); 
tmp2 = secondParentNode->clone(); 
this->operation = tmp2->operation; 
this->val = tmp2->val; 
this->lChild = tmp2->lChild; 
this->rChild = tmp2->rChild; 
secondParentNode = tmp; 

この時点で、私は既に交換される各サブツリーの位置を決定しています。 "this"ポインタは最初の交換ポイントを表し、secondParentNodeは2番目を表すopNodeポインタです。

2つの問題がここにあります

最初の交換は、ノードが子を1つしか持っていた状況を作り出すことができるということです。私はこれがどう起こっているのかを特定することに失敗しています。

2番目の、おそらく情報の関連するビット、一度this-> lChildがtmp2-> lChildに設定され、this-> rChild = tmp2-> rChildに設定されていれば、secondParentNode-> lChildかsecondParentNode-> rChildはnullでした。これにより、segfaultが少なくともいくらか一貫して発生します。

クローン(ディープコピー)機能は機能しませんか?もしそうなら、どうしてですか?これらの問題の原因となる可能性のあることについての考えは高く評価されます。

struct opNode 
{ 
    string operation; 
    double val; 
    opNode* lChild; 
    opNode* rChild; 
    opNode* clone(); 
}; 

と関連するクローン機能:

opNode* opNode::clone() 
{ 
    if(this != nullptr) 
    { 
     opNode* n = new opNode(); 
     n->val = val; 
     n->operation = operation; 
     n->rChild = rChild->clone(); 
     n->lChild = lChild->clone(); 
     return n; 
    } 
    return nullptr; 
} 

EDIT * 要求されたとして、交換機能

opNodeは私のノードクラスです。 randPoint1とrandPoint2を取ることによって決定されるuniform distribution

uniform_int_distribution<int> dist(0, mate[k].root->count(0) - 1); 
メイト[k]は、ルート・ツリー・ポインタであり、カウントのように定義される

int opNode::count(int c) 
{ 
    if(this != nullptr) 
    { 
     c++; 
     if(lChild != nullptr) 
      c += lChild->count(0); 
     if(rChild != nullptr) 
      c += rChild->count(0); 
     return c; 
    } 
    return 0; 
} 

交換機能:

void opNode::recombination(opNode*& secondParentNode, int& randPoint1, int& randPoint2, bool& done) 
{ 
    if(done) 
     return; 
    if(secondParentNode != nullptr && !done) 
    { 
     if(randPoint2 > 0 && secondParentNode->lChild != nullptr) 
     { 
      randPoint2--; 
      recombination(secondParentNode->lChild, randPoint1, randPoint2, done); 
     } 

     if(randPoint2 > 0 && secondParentNode->rChild != nullptr) 
     { 
      randPoint2--; 
      recombination(secondParentNode->rChild, randPoint1, randPoint2, done); 
     } 
    } 
    if(this != nullptr && randPoint2 == 0 && !done) 
    { 
     if(randPoint1 > 0 && lChild != nullptr) 
     { 
      randPoint1--; 
      lChild->recombination(secondParentNode, randPoint1, randPoint2, done); 
     } 
     if(randPoint1 > 0 && rChild != nullptr) 
     { 
      randPoint1--; 
      rChild->recombination(secondParentNode, randPoint1, randPoint2, done); 
     } 
    } 
    if(this != nullptr && secondParentNode != nullptr && randPoint1 == 0 && randPoint2 == 0 && !done) 
    { 
     opNode* tmp = new opNode(); 
     opNode* tmp2 = new opNode(); 
     tmp = this->clone(); 
     tmp2 = secondParentNode->clone(); 
     this->operation = tmp2->operation; 
     this->val = tmp2->val; 
     this->lChild = tmp2->lChild; 
     this->rChild = tmp2->rChild; 
     secondParentNode = tmp; 
    } 
} 
+0

だけはさておき(あなたが便利に提供していないとして、私は閉じるために投票し

私たちは、としての機能を書き換えることができます例)、最初のコードスニペットは何らかの理由で2つのノードをリークしています。また、「読むことのできないテキストの壁」は、質問のための良い外観ではありません。 – Useless

+0

この文脈では、有用な例として何を定義していますか? – s0teric

+0

バイナリツリーはそこで最も複雑なデータ構造ではありませんが、あなたがまだいることは、 'tmp = new OpNode(); ... tmp = this-_clone()'または 'this!= nullptr'初心者です。私があなたの同僚であっても、私はこれをデバッグすることはしません。問題は、テストせずにあまりにも多くのコードを書いたことです。 – MSalters

答えて

0

rChildまたはlChildnullptrの場合は、rChild->clone();またはlChild->clone()をコールすると、segmen失敗する。為替のコードは以下のように簡略化することができる

void opNode::clone(opNode* n) 
{ 
    if (n) 
    { 
     n->val = val; 
     n->operation = operation; 
     if (rChild) 
     { 
      if (n->rChild) 
      { 
       // release all right children. 
      } 
      n->rChild = new opNode; 
      clone(n->rChild); 
     } 

     if (lChild) 
     { 
      if (n->lChild) 
      { 
       // release all left children nodes. 
      } 
      n->lChild = new opNode; 
      clone(n->lChild); 
     } 
    } 
} 

opNode* tmp = new opNode; 
clone(tmp); 
secondParentNode->clone(this); 
tmp->clone(secondParentNode); 
+0

私はヌルの子供のsegfaultingが問題だとは思わない。私は正常に以前にクローン関数を使用します。前のクローン関数が1つの子を定義し、他の子を定義できない理由を説明していない限り、有効なバイナリ検索ツリーを入力として仮定します。さらに、この変更されたコードは、malloc.c:3302に別のsegfaultを引き起こします。 – s0teric

+0

'opNode'を作成するときに' rChild'と 'lChild'を' nullptr'に初期化しますか?メンバが 'nullptr'に初期化されると、' opNode'に左または右の子がない場合、コードは直ちにセグメンテーションされます。 – Kai

+0

これは間違っています。ヌルクラスポインタの関数を呼び出すことができます。私はテストし、このコードが動作し、期待される結果が得られます:opNode * n = new opNode(); int a = n-> lChild-> count(0); a = 0; cout << a << endl;はい、opNode lChildとrChildはnullptrに初期化されます。 – s0teric