2017-01-27 6 views
1

私はバイナリ検索クラスを持っています。私は特別なノードを削除するための関数を書こうとしていますが、わかりません。 基本的なクラスがある:bstツリーの削除

class Node { 
    friend class Tree; 
private: 
    long long rep; 
    Node *left, *right; 
    string data; 
public: 
    Node(string d) 
     : data(d), left(NULL), right(NULL), rep(1) {} 
}; 

class Tree { 
private: 
    Node *root; 
public: 
    void delete_node(Node *cur , string s); 
    void delete_node_helper(string s); 
}; 
+0

最良の方法は、スマートポインタを 'Node *'の代わりに 'std :: unique_ptr 'として使用することです。 – Jarod42

+0

ノードをどのように正確に削除したいですか?プレースホルダで置き換えるか、実際に削除しますか?この削除後にツリーの再バランスを行う必要がありますか?予想される漸近複雑さは何ですか? – alexeykuzmin0

+0

そして 'rep'とは何ですか? rep3: – alexeykuzmin0

答えて

0

バイナリ検索ツリーからのノードの削除中3つの部分があります:

  1. は、削除するノードを検索します。
  2. ノード(空きメモリなど)を削除します。
  3. 削除されたノードの子をマージします。あなたの特定のコード例で

は、私がvoid delete_node(Node *cur, string s);の責任であるべきノードを削除、ノードを探していることはvoid delete_node_helper(string s);の責任であることを言うだろう、と子供をマージすることは、新しく作成された者の責任でなければなりません関数。

最初の2つの部分のアルゴリズムが非常に厳密であることを考えると、3番目の部分だけを詳細に説明します。

BST(どちらが残っていてどちらが正しいか)をマージするには、誰がその子になるかを決定し、必要に応じて再帰的マージを実行する必要があります。コードは次のようになります。

Node* merge(Node* left, Node* right) { 
    if (left == nullptr) { 
     return right; 
    } 
    if (right == nullptr) { 
     return left; 
    } 
    if (rand() & 1) {        // <- chose parent 
     left->right = merge(left->right, right); 
     return left; 
    } 
    right->left = merge(left, right->left); 
    return right; 
} 

マークされた行では、実際にどのノードがその親であるかを決定します。この特定の例では、結果はランダムであるが、他の戦略を実装することもできる。たとえば、ツリーのすべてのノードに高さ(またはサイズ)を格納し、大きなツリールートの小さいツリールートの子ノードにすることができます。

+0

パート1と2に不明な点がある場合は、ご意見ください。 – alexeykuzmin0

+0

このような場合に 'rand()'を使用しないでください。何かがあれば、実際の利益を得ることなく、関数呼び出しと条件分岐を行わなければならないため、パフォーマンスが低下します。サブツリーの高さの使用に関するあなたの発言ははるかに優れています! –

+0

@ G.Sliepenツリー構造を変更できない場合(つまり、高さや大きさなどを格納しない)に 'rand() 'の代わりに何を使用することをお勧めしますか?私は個人的にはもっと良い解決策を知らない。 – alexeykuzmin0

関連する問題