2016-04-14 7 views
3

は、次のことを想定しますどのようにポインタをクラスオブジェクトのポインタの中にドラッグし、それらを再帰的に割り当ててポインタを返すか? C++

  • 私はPersonというクラスがあります:私はPersonオブジェクトのリストを格納するLinked_Listデータ構造を使用し

class Person { 
 
    public: 
 
    Person(); 
 
    ~Person(); 
 
    int compare(const Person & compared); //compare the names using strcmp() 
 
    void display(); 
 
    
 
    protected: 
 
    char * name; 
 
    int age; 
 
};

  • を:

class Linked_List { 
 
    public: 
 
    Linked_List(); 
 
    ~Linked_List(); 
 
    Person * retreive(Person, Node *, int &); 
 
    void insert(Person); 
 
    int remove_all(); 
 
    int display_all(); 
 
    
 
    protected: 
 
    Node * head; 
 
};

  • retrieve()関数は、関数(再帰的)に渡される一方と同じ名前を持つPersonオブジェクトのリストを返すべきです。

Person * Linked_List::retreive(Person target, Node * current, int & matches) { 
 
    if (current == NULL) { 
 
     Person * persons = new Person[matches]; 
 
     return persons; 
 
    } 
 
    if (target.compare(current->getData()) == 0) { 
 
     return retreive(target, current->getNext(), ++matches); //recursive call 
 
    } 
 
    return retreive(target, current->getNext(), matches); //recursive call 
 
}

この関数は三つの引数

1 - 私が探していた人になります。 (リスト上の他の名前と名前を比較する)

2-ヘッドポインタ。

3ターゲットの同じ名前のリストにあるPersonのオブジェクトの番号Person。 1で、この関数は基本的に再帰的にLinked_Listと毎回を通じて横断

が一致Personが発見されたmatches増加を(リストで発見されたのと同じ名前を持つ人の動的配列を割り当てるため)、その後、再帰呼び出しを行いますトラバースを続けるリストの終わりに達するまで、Personの配列が動的に割り当てられます。それから私は自分の問題に到達する。私は、personsの配列内の一致として見つかったPersonの各オブジェクトを格納(割り当て)できる方法を見つけていない限り、この関数をうまく動作させる方法を考えることができませんでした。再帰呼び出し)。関数はPersonの配列を返すので、その後、私は内書きます

だから、私が本当にやろうとしていますがこのような何か(これは間違っているが、ちょうど明確にするため)であります第二の条件

return (retreive(target, current->getNext(), matches))[matches++] = current->getPerson();

私はPersonオブジェクトの配列に同じ名前を持つすべてのPersonを保存したいが、私はまた、私は再帰呼び出しの最後に到達するまで待たなければならないので、私は一致する人数の正しいサイズで配列を初期化することができますが、私はまたPersonオブジェクトの配列(*)を返す必要があります。

+0

あなたは人を格納するために動的な繰り返し容器を使用すると考えましたか? ( 'std :: vector'やそれに類する実装のように)次に、最初に数えて2回リストを繰り返した後、正しいPersonの配列を返す必要はありません。 –

+0

@ChrisBritt私は実際に2回横断していません。これが少し難しい問題です。ありがとう、私はあなたが提案したものを検討します。しかし、好奇心のために、問題解決のための解決策があるかどうかを待つか、そうでないかもしれません。 – Bader

+0

ちょうど不思議なことに、 'compare'は一致すると0を返し、一致しない場合は0を返します。 (もしあなたが追加情報を渡しているのであれば、可読性のためにboolを使いたいかもしれません)。 –

答えて

3

単純な事実を理解すると、答えは非常に簡単です。与えられた反復で、nmatchesが0で、compare()のクレームがターゲットと一致するレコードを見つけたとします。

これはこれが最初に一致するレコードであることを意味します。つまり、返された配列では、この一致はpersons[0]になります。

nmatchesが1の場合、この一致はpersons[1]になります。以下同様です。

これは、これは単純に、なることを意味します。それだけです

Person * Linked_List::retreive(Person target, Node * current, int & matches) { 
    if (current == NULL) { 
     Person * persons = new Person[matches]; 
     return persons; 
    } 
    if (target.compare(current->getData()) == 0) { 
     int n=matches; 

     auto p=retreive(target, current->getNext(), ++matches); 
     p[n]=current->getData(); 
     return p; 
    } 
    return retreive(target, current->getNext(), matches); //recursive call 
} 

を。あなたの宿題は、醜いnewを取り除き、std::vectorを使ってすべてを書き直すことです。現代のC++では、手動ではほとんどありませんnewdelete何か。すべてのニーズと欲求のためのコンテナがあります。また、コンテナが適切に使用されている場合、特別なボーナスとして、メモリリークは発生しません。どのような交渉!

0

このサンプルでは、​​テンポラリキャッシュとしての役割を果たすためにstd::vector<Person*>を使用しています。ポインタの配列に加えて、このベクトルもユーザーに返します。 Node :: getData()がデータ要素へのポインタを返すという前提のもとで動作しています。 (かなり標準的な方法であることは間違いありません)また、戻り値の型をvoidに変更することで、配列の必要性を完全に取り除くことができます。データが含まれているstd :: vectorも返されます。 (new/deleteでアレイを使用することにより、STLコンテナの汎用性にやや時代遅れである。)

ちょうどメモとして、可変int & matchesについてstd::vector::size()内に含まれます。

Person * Linked_List::retreive(Person target, Node * current, std::vector<Person*>& _persons) { 
    if (current == NULL) { 
     Person * persons = new Person[_persons.size()]; 
     for(int i(0); i < _persons.size(); ++i) 
     { 
      persons[i] = &_persons[i]; 
     } 
     return persons; 
    } 
    if (target.compare(current->getData()) == 0) { 
     _persons.push_back(current->getData()); 
     return retreive(target, current->getNext(), _persons); //recursive call 
    } 
    return retreive(target, current->getNext(), _persons); //recursive call 
} 
関連する問題