AVL ツリー ウィキペディアのページに次のコメントがあることに気付きました。
「各ノードがそのサブツリーのサイズ (それ自体とその子孫を含む) を追加で記録する場合、ノードは O(log n) 時間でインデックスによって取得することもできます。」
私はグーグルで検索し、インデックスによるアクセスについて言及している場所をいくつか見つけましたが、作成するアルゴリズムの説明を見つけることができないようです。
どうもありがとう
[更新] ありがとうございます。@templatetypedef の回答が見つかった場合は、@user448810リンクの 1 つと組み合わせて、特に役立ちます。特にこのスニピット:
「これら両方の機能の鍵は、ノードのインデックスがその左の子のサイズであるということです。左の子を介してツリーを下降している限り、ノードのインデックスを取得するだけです。しかし、移動する必要がある場合右の子を介してツリーをたどると、除外したツリーの半分が含まれるようにサイズを調整する必要があります。」
私の実装は不変であるため、各ノードが構築時にサイズを計算するため、リバランス時に追加の作業を行う必要はありませんでした (リンクされたスキーム impl と同じ)。
私の最終的な実装は次のようになりました。
class Node<K,V> implements AVLTree<K,V> { ...
public V index(int i) {
if (left.size() == i) return value;
if (i < left.size()) return left.index(i);
return right.index(i - left.size() - 1);
}
}
class Empty<K,V> implements AVLTree<K,V> { ...
public V index(int i) { throw new IndexOutOfBoundsException();}
}
これは他の実装とは少し異なります。バグがあると思われる場合はお知らせください。