このデータ構造を実装する 1 つの可能な方法は、順序統計ツリーとハッシュ テーブルのハイブリッドを使用することです。
順序統計ツリーは、バランス型二分探索ツリーの一種で、通常の二分探索ツリー操作に加えて、さらに 2 つの操作をサポートします。
- 指定された要素よりも小さいツリー内の要素の数を返すランク(キー)、および
- (k) を選択すると、ツリーで k 番目に小さい要素が返されます。
順序統計ツリーは、ローテーション中に保持される追加情報を使用して、通常のバランスのとれた二分探索ツリー (赤/黒ツリーまたはAVL ツリーなど) を拡張することによって構築できます。このようにして、注文統計ツリーのすべての通常の BST 操作を O(log n) 時間で実行し、追加の操作も O(log n) 時間で実行できます。
ここで、キー/パーセンタイル スコアではなく、純粋に値のスコアを格納していたとします。この場合、次のようにパーセンタイル ルックアップを実装するのは非常に簡単です。すべての値を注文統計ツリーに格納します。特定の値のパーセンタイル スコアを決定するには、順序統計ツリーでランク操作を使用して、その値が表示されるインデックスを調べます。これにより、0 から n - 1 (n はツリー内の要素の数) の範囲の数値が得られ、順序統計ツリー内のそのスコアの位置が示されます。次に、必要に応じて、その数値に 99 / (n - 1) を掛けて、0 から 99 の範囲で実行される値のパーセンタイル スコアを取得できます。
パーセンタイルを超える最小値を決定するには、次のように選択操作を使用できます。0 ~ 99 のパーセンタイルが与えられた場合、そのパーセンタイルに 99 / (n - 1) を掛けて、0 ~ n - 1 の間の実数を取得します。その数の上限を取ると、0 から n - 1 までの範囲の自然数が生成されます。注文統計ツリーで選択操作を使用すると、指定されたパーセンタイル以上の範囲内の最初の値を見つけるために使用できます。
ただし、これらの操作は、キーと値のペアではなく、データ構造に純粋な値があることを前提としています。この操作をキーと値のペアで機能させるには、次のようにデータ構造を拡張します。
- 値を格納するだけでなく、キーと値のペアを各ノードに格納します。順序統計ツリーは、キーと値のペアを値だけでソートし、キーはサテライト データとして持ち運ばれます。
- キーを関連付けられた値にマップするセカンダリ ハッシュ テーブルを格納します。
これら 2 つの変更により、データ構造に必要な機能を実装できるようになります。キーによるパーセンタイル ルックアップを実行するデータ構造を取得するには、まず、指定されたキーを使用してハッシュ テーブルにクエリを実行し、関連付けられた値をルックアップします。次に、前に行ったように、値に対してパーセンタイル ルックアップを行います。値が特定のパーセンタイル以上の最初のキーを示すデータ構造を取得するには、上記のように注文統計ツリーで通常のパーセンタイル検索操作を実行し、次に特定の値に関連付けられたキーを検索します。
ハッシュテーブルが連鎖ハッシュを使用すると仮定すると、各操作に必要な時間は次のようになります。
- Insert : 値/キー ペアを順序統計ツリーに挿入する O(log n) 時間と、キー/値ペアをハッシュ テーブルに挿入する O(1) 償却時間。合計時間は O(log n) 償却されます。
- 削除: 順序統計ツリーから値/キー ペアを削除する O(log n) 時間と、ハッシュ テーブルからキー/値ペアを削除するための (1) 償却時間。合計時間は O(log n) 償却されます。
- パーセンタイル: キーに関連付けられた値を検索するのに O(1) 予想される時間、ランク操作を行う O(log n) 時間、およびランクをパーセンタイルにマップする O(1) 余分な時間。合計時間は O(log n) と予想されます。
- Find-Percentile : パーセンタイルをランクにマップするのに必要な O(1) 時間、および選択操作を実行するのに必要な O(log n) 時間。最悪の場合、合計時間は O(log n) です。
お役に立てれば!