2012-04-28 9 views
0

BSTでn番目に小さい要素を見つけるアルゴリズムを書いたが、n番目に小さいものの代わりにルートノードを返す。したがって、ノードを7 4 3 13 21 15の順番で入力すると、find(root、0)の呼び出し後のこのアルゴリズムは、3ではなく7のNodeを返し、find(root、1)の呼び出しでは4の代わりに13を返します。思考?バイナリ検索ツリーでn番目に小さい要素を見つける

Binode* Tree::find(Binode* bn, int n) const 
{ 
    if(bn != NULL) 
    { 

    find(bn->l, n); 
    if(n-- == 0) 
     return bn;  
    find(bn->r, n); 

    } 
    else 
     return NULL; 
} 

とBinode

class Binode 
{ 
public: 
    int n; 
    Binode* l, *r; 
    Binode(int x) : n(x), l(NULL), r(NULL) {} 
}; 
+0

これまでに行ったデバッグは何ですか? –

+2

あなたのコードは意味的にもアルゴリズム的にも意味をなさない。 – Corbin

+1

find(bn-> l、n)とfind(bn-> r、n)の結果は使用しません。 – user396672

答えて

1

の定義コードを持ついくつかの問題がある:

1)意図したとおりに機能を想定値(正しいノードが、動作している戻りfind())はその値を呼び出しチェーンに伝播しないので、トップレベルの呼び出しは、(見つかった)見つかった要素について知りません

Binode* elem = NULL; 
elem = find(bn->l, n); 
if (elem) return elem; 
if(n-- == 0) 
    return bn;  
elem = find(bn->r, n); 
return elem; // here we don't need to test: we need to return regardless of the result 

2)あなたは正しい場所にnの減少を行うにもかかわらず、変更が呼び出しチェーンで上向きに伝播しません。このパラメータは参照によって渡される必要があります(関数シグネチャ内のintの後に&を書き留めておきます)。したがって、変更は元の値で行われます。

です。

Binode* Tree::find(Binode* bn, int& n) const 

効率的にそれ自体で二分探索木のn番目の最小の要素を取得することはできません、私が提案した変更をテストしていませんが、彼らが進行

+0

あなたの答えはアッティラに感謝します。Ambrozが提案したソリューションを使用して、各ノードの左のサブツリーのサイズを維持しました。すべてのノードにこの追加情報を持たせることで、要求されたノードを簡単に見つけることができます。 – lukas7674

+0

@ lukas7674 - あなたが問題を解決するのに役立ちましたら、Ambrozさんの答えを受け入れてください。 – Attila

2

のために正しい方向にあなたを置く必要があります。ただし、各ノードにサブツリー全体のノード数を示す整数を保持すると、これが可能になります。 my generic AVL tree implementationから:

static BAVLNode * BAVL_GetAt (const BAVL *o, uint64_t index) 
{ 
    if (index >= BAVL_Count(o)) { 
     return NULL; 
    } 

    BAVLNode *c = o->root; 

    while (1) { 
     ASSERT(c) 
     ASSERT(index < c->count) 

     uint64_t left_count = (c->link[0] ? c->link[0]->count : 0); 

     if (index == left_count) { 
      return c; 
     } 

     if (index < left_count) { 
      c = c->link[0]; 
     } else { 
      c = c->link[1]; 
      index -= left_count + 1; 
     } 
    } 
} 
上記のコードで

node->link[0]node->link[1]nodeの左と右の子であり、node->countnodeのサブツリー全体のノード数です。

上記のアルゴリズムは、ツリーが均衡していると仮定すると、O(logn)時間の複雑さを持ちます。また、これらのカウントを保持すると、別の操作が可能になります。ノードへのポインタがあれば、インデックス(効率的にインデックスを求めることができます)を求めることができます。リンクされたコードでは、この操作はBAVL_IndexOf()と呼ばれます。

ツリーが変更されるとノードの数を更新する必要があることに注意してください。これは、時間の複雑さの変化なしに(漸近的に)行うことができる。

+0

ありがとうございますAmbroz、これは素晴らしい、私は決して再帰的な方法はそれをはるかに簡単だろうと考えていない:) – lukas7674

+0

@ lukas7674ここのポイントは、反復対反復ではなく、ノード数。このアルゴリズムは、再帰的な方法で簡単に表現できます(ただし、遅くなる可能性があります)。 –

+0

もう一度、私はちょうど再帰的にやったし、それは動作します!そんなに学ぶ... – lukas7674

関連する問題