11

検索機能とランク機能を備えた ADT が必要です。つまり、STL マップのインターフェイスに加えて、関数「int get_rank(key)」が必要です。

このような関数の標準的な実装では、自己均衡検索ツリー (STL マップ/セットで使用される黒赤ツリーなど) のすべてのノードで追加の整数フィールドをサポートおよび更新する必要があります。しかし、STLマップ/セットはこれを行わないようです。

可能な限り最高の時間複雑度を持つ標準コンテナー (STL、Boost) に基づくソリューションを探しています。 key も O(log n) かかります。

要素のランクとは、マップ/セットのすべての要素のソートされたシーケンスにおける要素の位置を意味します。

例。セット = {0, 4, 6, 7, 8} ランク (0) = 1、ランク (4) = 2、ランク (6) = 3、ランク (7) = 4、ランク (8) = 5。

私たちの意見では、上記の時間の複雑さの制約の下では、1 つはキーで並べ替え、もう 1 つはランクで並べ替えた 2 つのマップの組み合わせでは問題を解決できません。

ありがとう。

4

4 に答える 4

5

与えられたキー K のランクは、K 以下のキーの数です。

たとえば、s = {1, 3, 4, 6, 9} とします。次に、ランク (1) = 1、ランク (4) = 3、ランク (9) = 5 です。

STL 関数 distance() を使用して、集合 s に現れる要素 x のランクを計算できます。

ランク = 距離 (s.begin(), s.find(x));

問題は、その時間の複雑さが O(n) であることです。

キーとランクでインデックス付けされた提案された 2 つのマップ (またはセット) は正しいソリューションではないことに注意してください。問題は、1 つの要素の変更が他の多くのランクに影響を与えることです。たとえば、上のセット s に要素 0 を追加すると、既存のすべての要素のランクが変更されます: s' = {0, 1, 3, 4, 6, 9}。ランク (1) = 2、ランク (4) = 4、ランク (9) = 6。

ありがとう。

于 2010-02-18T22:44:09.633 に答える
2

キーを保存するのではなく、各ノードがその前のノードからの距離を順序通りにトラバーサルして保存することを除いて、赤黒ツリーに似た「ランク付けされた赤黒ツリー」を実装しました。

これは、最初のノードの「ランク」が1ではなく0であることを除いて、まさにあなたが望むことを行います(必要に応じて1を加算/減算できます)。

私の解決策は PUBLIC DOMAIN で、通常の赤黒ツリーのパブリック ドメイン チュートリアルに基づいています。すべての操作 (挿入、削除、検索、ランクの決定を含む) は、データ構造内の要素数に関して対数時間になります。

ここで見つけることができます: http://code.google.com/p/options/downloads/list

上記のリンクから最新バージョンを取得する必要があります。現在 (この記事の執筆時点) rrb_v4_release.cpp.

于 2010-12-28T04:39:35.953 に答える
1

コンテナのような他のマップを使用できます。
フィールドのサイズを維持することで、二分探索木をランダム アクセスしやすくすることができます。
これが私の実装です...
標準スタイル、ランダムアクセスイテレータ...
サイズバランスのとれたツリー...
https://github.com/mm304321141/zzz_lib/blob/master/sbtree.h
およびB +ツリー...
https: //github.com/mm304321141/zzz_lib/blob/master/bpptree.h

于 2015-10-21T03:13:37.160 に答える
0

rank値と連続して格納できれば、そのような長さに移動する必要がないため、実際にはルートからの距離を意味していると思います。

この場合、比較述語が使用される回数からランクを推定できるため、「外部」で実行できると思います...

namespace detail
{
  template <class Comparator>
  class CounterComparator: Comparator
  {
  public:
    CounterComparator(size_t& counter):
        Comparator(), mCounter(&counter) {}
    CounterComparator(Comparator comp, size_t& counter):
        Comparator(comp), mCounter(&counter) {}

    template <class T, class U>
    bool operator()(T& lhs, U& rhs) const
    { 
      ++(*mCounter);
      return this->Comparator::operator()(lhs,rhs);
    }
  private:
    size_t* mCounter;
  };
} // namespace detail

template <
  class Key, 
  class Value, 
  class Cmp = std::less<Key>, 
  class Allocator = std::allocator< std::pair<const Key,Value> >
>
class SuperMap
{
  typedef detail::CounterComparator<Cmp> Comparator;
public:
  SuperMap(): mCounter(0), mData(Comparator(mCounter)) {}

  Value& operator[](const Key& key) { return mData[key]; }

  size_t rank(const Key& key) const
  { 
    mCounter = 0; mData.find(key); return mCounter;
  }

private:
  typedef std::map<Key,Value, Comparator, Allocator> data_type;

  mutable size_t mCounter;
  data_type mData;
}; // class SuperMap

int main(int argc, char* argv[])
{
  SuperMap<int,int> superMap;
  superMap[1] = 42;
  std::cout << superMap.rank(1) << std::endl;
}

// outputs
// 2

テストの数をカウントしますstd::mapが、正しいキーを取得するとすぐにテストを停止するため...大丈夫なはずです:)おそらく、代わりにランクを取得するためにそこに推測するオフセット(1または2)があります。

あなたがより良い定義を与えたなら、rank私はもう少し働くかもしれませんが、間違った方向に多くの時間を費やしたくありません.

于 2010-02-18T17:55:52.707 に答える