1

キーと値のペアを 3 次ツリーに追加するメソッドを作成しようとしていますが、マークされたコードに到達するたびに segfault が発生するため、明らかに何か間違っています。

void Tree::add(int k, Node *&r)
{
    cout<<"add"<<endl;
    if(r==NULL){
        r = new Node(k);
        //check(heap area);
    }

問題コードの開始

    else if(r->keyCount == 1){
        cout<<"adding second key";
        if(r->getKey() < k){
            Node * temp = new Node(r->getKey(),k,r->data[0],0);
            delete r;
            r = temp;
            r->keyCount++;
            cout<<"test"<<endl;
        }
        else
        {
            Node * temp = new Node(k,r->getKey(),0,r->data[0]);
            delete r;
            r = temp;
            r->keyCount++;
            cout<<"test"<<endl;
    }

終了コード

    }
    else if(k < r->getKey())
    {
        cout<<"left"<<endl;
        add(k,r->child[Node::L]);
    }
    else if(r->keyCount > 1 && k < r->getKey(1))
    {
        cout<<"middle"<<endl;
        add(k,r->child[Node::M]);
    }
    else if(r->keyCount > 1 && k > r->getKey(1))
    {
        cout<<"right"<<endl;
        add(k,r->child[Node::R]);
    }
    else
        r = new Node(k);
}

私がやろうとしているのは、この特定のノードで使用されている 2 つのキーのうち 1 つしかない場合、現在のノードを適切な場所にキーを持つ新しいノードに置き換えることです (key[ 0]、key[1] のより大きい値) これを適切に行うにはどうすればよいですか?

私のコードは明らかに古いノードのアドレスとポインタの両方を削除しますが、ポインタを新しいノードに適切に再割り当てしません。

更新されたコードを編集します。出力は次のとおりです。

% p4
Enter pairs consisting of an int and a double. I create a
ternary tree, keeping the data in order, by int. Finish entering
data by pressing ^d
2 2
add
Entering the pair: 2, 2
1 1
add
adding second key to current node
test
Entering the pair: 1, 1
-1 -1
add
left
add
Entering the pair: -1, -1
3 3
add
right
Segmentation Fault

編集 2 すべてのコードを確認したい場合は、プロジェクト全体を含む zip へのリンクを次に示します: http://sdrv.ms/WSrLfv

編集 3 その他のエラー データ - クラッシュ時の gdb からの出力

Program received signal SIGSEGV, Segmentation fault.
0x08051628 in getData (x=@0x8047554) at testTree.cc:26
26            x[k]=d;
Current language:  auto; currently c++

編集 4 gdb を介して segfault に進みます。

Breakpoint 1, Tree::add (this=0x8047554, k=3, r=@0x8047554) at tree.cc:58
58          cout<<"add"<<endl;
(gdb) n
add
61          if(r==NULL){
(gdb) n
65          else if(r->keyCount == 1){
(gdb) n
87          else if(k < r->getKey())
(gdb) n
92          else if(r->keyCount > 1 && k < r->getKey(1))
(gdb) n
97          else if(r->keyCount > 1 && k > r->getKey(1))
(gdb) n
99              cout<<"right"<<endl;
(gdb) n
right
100             add(k,r->child[Node::R]);
(gdb) n

Breakpoint 1, Tree::add (this=0x8047554, k=3, r=@0x806416c) at tree.cc:58
58          cout<<"add"<<endl;
(gdb) n
add
61          if(r==NULL){
(gdb) n
62              r = new Node(k);
(gdb) n
107     }
(gdb) n
107     }
(gdb) n
Tree::operator[] (this=0x8047554, index=3) at tree.cc:47
47          return *(locate(index,root)->data);
(gdb) n
48      }
(gdb) n

Program received signal SIGSEGV, Segmentation fault.
0x08051628 in getData (x=@0x8047554) at testTree.cc:26
26            x[k]=d;
(gdb)
4

1 に答える 1

2

これは機能するはずです。

あなたの編集に応えて: あなたの出力に興味深いものがあることに気付きました:

-1 -1
add
left
add
Entering the pair: -1, -1

再帰呼び出しのために、「左」と表示され、その後「追加」と表示されていることに注意してください。ただし、プログラムをクラッシュさせる入力では、後に「追加」が表示されません。

3 3
add
right
Segmentation Fault

関数を見るとTree::locate

Node * Tree::locate(int k, Node *rt) const
{
if(rt==NULL)
    return rt;
if(k==rt->getKey())
    return rt;
if(rt->keyCount>1 && k==rt->getKey(1))
    return rt;
if(k < rt->getKey())
{
    return locate(k,rt->child[Node::L]);
}
else if(rt->keyCount>1 && k < rt->getKey(1))
{
    return locate(k,rt->child[Node::M]);
}
else if(rt->keyCount>1 && k<rt->getKey(1))
{
    return locate(k,rt->child[Node::R]);
}
else
    return NULL;
}

この行:

else if(rt->keyCount>1 && k<rt->getKey(1))

は前回と同じ状態なので完全に飛ばしています。

于 2013-03-19T01:53:57.000 に答える