2013-06-11 7 views
5

私は、数((1,1,2)、(1,2,5)、(2、...)のタプルのソートされたリストから構築されたツリー(基本的にプレフィックスツリーですが、 1,0)など)、それぞれが単一のスカラー値(intまたはdoubleの可能性が高い)に関連付けられています。一度だけ構築されてから何度も繰り返し/検索されるので、各ノードの子を保持するためにstd :: vectorsを使用する予定です。ツリーを検索するには、std :: lower_boundを呼び出すだけで、各ノードの_childrenベクトルでバイナリ検索を行う必要があります。各ベクトルには、各ノードとそれぞれのキーのstd :: pairsが含まれています。ただし、下位ノードには、各タプルの最後のエントリとそれぞれの値からなるペアを持つベクトルが含まれている必要があります。したがって、BranchNodeとは異なる型である必要があります。コードは次のようになります。しかしC++:分岐ノードと葉ノードのクラスを分ける?

class GenNode 
{ 
}; 

template<typename key_type,typename value_type> 
class BranchNode : GenNode 
{ 
    void insert(std::pair< std::vector<key_type> , value_type>); 
private: 
    std::vector< std::pair<key_type,GenNode*> > _children; 
}; 

template<typename key_type,typename value_type> 
class LeafNode : GenNode 
{ 
private: 
    std::vector< std::pair<key_type,value_type> > _children; 
}; 

、各BranchNodeの子供が他のBranchNodesまたはリーフノードのどちらかにすることができるように、両方のクラスには役に立たないGenNodeクラスから継承しなければならないので、これは、本当に醜いです...ですがこれを行うより良い方法は?

+0

'Node'は、サブノードが追加されるまでの葉であり、分岐です。ちょうど 'Node'オブジェクトがあります。 –

+0

私はそれを効率の理由からしたくありません。私は葉ノードに空の_childrenベクタを持たせたくないのですが、おそらく "size = 0"と他の同様のメンバを格納しているでしょう。 –

+0

このブログ記事のコメントセクションに、異なるツリー実装のメリットについての議論があります。http ://math.andrej.com/2009/04/11/on-programming-language-design/ – Heatsink

答えて

2

両方の型を同じベクトルに格納する場合は、関連するクラス(共通の祖先から継承したクラスまたは継承したクラスの両方)を継承する必要があります。

空の共通の祖先を持つことは醜いように見えるかもしれません。しかし、検索アクション(および他の反復/処理)を仮想メソッドとして基本クラスに入れて、BranchNodeLeafNode(実装は異なる)に実装すれば、より洗練されたデザインを得ることができます。

この場合、ベースクラスもテンプレート化する必要があります。 私は何を意味することなどの基本クラスを持っている:

template<typename key_type,typename value_type> 
class GenNode { 
public: 
    virtual value_type search(key_type key) = 0; 
}; 
+0

私はこの設計アプローチを使用して、begin()メソッドとsearch()メソッドを共通インタフェースの中に置いてしまいました。 –

2

はい、次の2つの異なる種類が必要です。実際、このようなもの(Leaf OR Node)はdiscriminated unionと呼ばれます。

これを実装するにはいくつかの方法がありますが、おそらく最も一般的なのは2つの派生クラスを持つ共通基本クラスを持つC++です。

共通のベースを持つ興味深い選択肢はboost::variantrecursive wrapperを使用しています。これは、ポインタの使用を避けるため(そしてあなたのためにメモリ管理を行うため)、特に興味深いものです。

+1

区別クラスの代わりに基本クラス+派生クラスパターンが使用されることがありますが、実際には区別されたクラスではありません。違いは、差別化された組合は新しい変種では拡張できないということです。つまり、区別された共用体は、非 'Leaf'、非' Branch'ツリーノードは存在しないと主張します。クラス階層は、新しいサブクラスを定義できるため、これを保証しません。 – Heatsink

+0

@Heatsink差別化された共用体は*継承を介して実装されます。あなたが言ったように実装は完璧ではありませんが、私はまだこのケースであなたが実装しようとしていることは、実質的に差別化された組合であると主張します。 –

関連する問題