0

二分探索木を構築する C++ コードを書きました。コードは正しくコンパイルされましたが、実行可能ファイルを実行しようとすると、セグメンテーション エラーが発生します。以下は私のコードです:

    #include <iostream>

using namespace std;

struct Node{
    Node *parent, *right, *left; 
    int data;
};

class bst{
    private:
    Node* root;

    public:
        bst (int data);
        void insert (Node * node, int data);
        void insert (int data);
        Node * search (int data);
        Node * search (Node * node, int data);
        // remove (Node * node, int data);
};

bst::bst (int data){
    root -> data = data;
}

void bst::insert (Node * node, int data){
    if (node == NULL){
        node -> data = data;
    }
    else if (data < node -> data){
        insert (node -> left, data);
    }
    else if (data > node -> data){
        insert (node -> right, data);
    }
}

void bst::insert (int data){
    insert (root, data);
}

Node * bst::search (Node * node, int data){
    if (node == NULL || node -> data == data)
        return node;
    else if (data < node -> data)
        return search (node -> left, data);
    else if (data > node -> data)
        return search (node -> right, data);
}

Node * bst::search (int data){
    search (root, data);
}

int main(){
    cout << "main entry\n";
    bst __bst (10);
    cout << "new causing problem\n";
    bst bst2(1);
//  bst *my_bst = new bst(10);
    cout << "tree created\n";
/*  my_bst -> insert(32);
    my_bst -> insert(3);
    my_bst -> insert(36);
    my_bst -> insert(93);
    my_bst -> insert(23);
    cout << "insertion completed\n";

    if (my_bst -> search(4) == NULL )
        cout << "4 does not exist\n";
    if (my_bst -> search(36) != NULL)
        cout << "36 exists in tree\n";
*/  return 0;
}

この問題をデバッグしているときに、興味深い観察結果に出会いました。main 関数にbst __bst (10) のみが含まれる場合。オブジェクト定義と「新しい原因\n」コメントの後に、何も出力されません。したがって、最初のオブジェクト定義が問題を引き起こしていると想定しました。しかし、bst bst2(1);を置くと、またはbst *my_bst = new bst(10); 主に、セグメンテーション違反が再び発生しますが、「新しい原因の問題\n」が出力される前ではありません。したがって、実行はその時点まで進みました。したがって、この場合、最初のオブジェクト定義は問題を引き起こしませんでした。

セグメンテーション違反の原因と、この奇妙なことが起こっている理由を誰かが教えてくれますか?

編集: コンストラクター コード中に NULL ポインターを逆参照しようとしていることを皆さんが指摘したように、提案された変更を行い、コードは正常に機能しました。しかし、私はそれらの変更がなくても機能する同様のプログラムを持っています。以下はそのためのコードです。

#include <iostream>

using namespace std;

struct Name{
    string first_name;
    string last_name;
};

class Person{
    public:
    Person (string first_name, string last_name){
            name -> first_name = first_name;
            name -> last_name = last_name;
    }   

    int get_age(){
            return age;
    }   

    void set_age (int new_age){
            age = new_age;
    }   

    string get_first_name(){
            return name -> first_name;
    }   

    string get_last_name(){
            return name -> last_name;
    }   

    private:
    Name * name;
    int age;
};

int main (){ 
    Person prince ("Prince", "Kumar");
    cout << prince.get_first_name() << endl;
    cout << prince.get_age() << endl;
    return 0;
}

この場合、プログラムは完全に正常に実行されます。Nameポインターにいくつかのスペースを割り当てるためのデフォルトのコンストラクターを実行しましたname。数値型には 0 の値を割り当て、ポインター、オブジェクト、および文字列には NULL を割り当てることを知っていました。私は正しいですか?

4

3 に答える 3

0
private:
    Node* root;

ルートはコンストラクターで初期化されていません

bst::bst (int data){
    root -> data = data;
}
于 2013-04-15T09:27:03.547 に答える
0

insert()when tree empty ケースで null ポインタを逆参照しています

于 2013-04-15T09:27:16.110 に答える
0

コンストラクターでは、メモリを割り当てずにポインターであるルートを逆参照しています。これは未定義の動作です。

bst::bst (int data){
  root -> data = data;
}

このようなもので十分です:, この問題のために

bst::bst (int data) : root( new Node ) 
                      ^^^^^^^^^^^^^^^^ 
{
  root -> data = data;
}

初期化リストを使用してメモリを割り当てるだけです。あなたのinsert方法にも同じ問題があります:

if (node == NULL){
    node -> data = data;
}

解決策は似ています:

node = new Node ;
node->data = data ;

これが機能するためには、初期化する必要がありますが、right正しくは、コンストラクターを使用することをお勧めします。leftparentNode

Node() : parent(NULL), right(NULL), left(NULL) {}

これらの修正により、動作するプログラムが得られるようです。

于 2013-04-15T09:28:12.307 に答える