C++ 中的排名树

发布于 2024-08-22 14:13:39 字数 466 浏览 6 评论 0原文

我们需要具有搜索和排名功能的 ADT。 也就是说,除了STL Map的接口之外,还需要一个函数'int get_rank(key)'。

这种功能的标准实现需要支持和更新自平衡搜索树(例如,在黑红树中,在STL映射/集合中使用)的每个节点中的额外整数字段。 但似乎STL映射/集不这样做。

我们正在寻找一种基于标准容器(STL、Boost)且具有最佳时间复杂度的解决方案: 查找/添加/删除元素需要 O(log n)(就像在 STL 映射/集合中一样), 通过键计算排名也需要 O(log n)。

元素的排名是指该元素在映射/集合的所有元素的排序序列中的位置。

例子。 设置 = {0, 4, 6, 7, 8} 等级(0)=1,等级(4)=2,等级(6)=3,等级(7)=4,等级(8)=5。

我们认为,在上述时间复杂度约束下,不能通过两个映射(一个按键排序,另一个按排名排序)的组合来解决该问题。

谢谢。

We need ADT having search and rank features.
That is, in addition to the interface of STL map, a function 'int get_rank(key)' is required.

Standard implementation of such function requires supporting and updating an extra integer field in every node of self-balanced searching tree (e.g., in black-red tree, used in STL map/set).
But it seems, STL map/set do not do this.

We're looking for a solution based on standard containers (STL, Boost) having the best possible Time Complexity:
finding/adding/erasing an element take O(log n) (like in STL map/set),
computing the rank by a key takes also O(log n).

By the rank of an element, we mean the position of the element in the sorted sequence of all the elements of the map/set.

Example.
set = {0, 4, 6, 7, 8}
rank(0)=1, rank(4)=2, rank(6)=3, rank(7)=4, rank(8)=5.

In our opinion, under Time Complexity constrains above, the problem cannot be solved by a combination of two maps one sorting by key and other sorting by rank.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

毅然前行 2024-08-29 14:13:39

给定密钥K的等级是小于或等于K的密钥的数量。

例如,让集合s = {1,3,4,6,9}。
那么rank(1) = 1,rank(4) = 3,rank(9) = 5。STL

函数distance()可用于计算集合s中出现的元素x的排名。

排名 = 距离(s.begin(), s.find(x));

问题是它的时间复杂度是O(n)。

请注意,提出的按键和按排名索引的两个映射(或集)不是正确的解决方案。
问题在于,一个元素的变化会影响许多其他元素的排名。
例如,将元素 0 添加到上面的集合 s 中会更改所有现有元素的排名:
s' = {0, 1, 3, 4, 6, 9}。
排名(1)= 2,排名(4)= 4,排名(9)= 6。

谢谢。

The rank of the given key K is the number of keys which are less or equal to K.

E.g., let set s = {1, 3, 4, 6, 9}.
Then rank(1) = 1, rank(4) = 3, rank(9) = 5.

The STL function distance() can be used for computing the rank of an element x appearing in the set s.

rank = distance(s.begin(), s.find(x));

The problem is that its time complexity is O(n).

Note that proposed two maps (or sets) indexed by key and by rank is not correct solution.
The problem is that a change of one element affects ranks of many others.
E.g., adding element 0 to the set s above change the ranks of all existing elements:
s' = {0, 1, 3, 4, 6, 9}.
rank(1) = 2, rank(4) = 4, rank(9) = 6.

Thanks.

三月梨花 2024-08-29 14:13:39

我实现了一个“排名红黑树”,它与红黑树类似,只是每个节点通过有序遍历存储与其前面的节点的距离,而不是存储键。

这正是你想要的,除了第一个节点的“等级”是 0 而不是 1(如果需要,你可以加/减 1)。

我的解决方案是公共域,基于常规红黑树的公共域教程。所有操作(包括插入、删除、查找和确定排名)都具有相对于数据结构中元素数量的对数时间。

您可以在这里找到它:
http://code.google.com/p/options/downloads/list

您应该从上面的链接获取最新版本,当前(截至撰写本文时)为 rrb_v4_release.cpp。

I've implemented a "ranked red-black tree" which is similar to a red-black tree except each node stores the distance from the node that precedes it via an in-order traversal, rather than storing a key.

This does exactly what you want, except the "rank" of the first node is 0 and not 1 (you can add/subtract 1 if needed).

My solution is PUBLIC DOMAIN and is based on a public domain tutorial for a regular red-black tree. All operations -- including insert, remove, find, and determine rank have logarithmic time with respect to the number of elements in the data structure.

You can find it here:
http://code.google.com/p/options/downloads/list

You should get the latest version from the above link, currently (as of this writing) rrb_v4_release.cpp.

南街女流氓 2024-08-29 14:13:39

您可以使用其他地图,例如容器。
保留一个大小的字段可以使二叉搜索树易于随机访问。
这是我的实现...
std 样式,随机访问迭代器 ...
大小平衡树...
https://github.com/mm304321141/zzz_lib/blob/master/sbtree。哈
和 B+树 ...
https://github.com/mm304321141/zzz_lib/blob/master/bpptree。哈

you can use some other map like containers .
keep a size fields can make binary search tree easy to random access .
here is my implementation ...
std style , random access iterator ...
size balanced tree ...
https://github.com/mm304321141/zzz_lib/blob/master/sbtree.h
and B+tree ...
https://github.com/mm304321141/zzz_lib/blob/master/bpptree.h

被翻牌 2024-08-29 14:13:39

我认为排名实际上是指距根的距离,因为如果它可以与值连续存储,则不必达到这样的长度。

我认为你可以“外部”执行此操作,因为在这种情况下,可以根据使用比较谓词的次数推断出排名...

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)来获得排名。

如果您对排名给出了更好的定义,我可能会多做一些工作,但我不想在错误的方向上花费太多时间。

I would suppose that by rank you actually mean the distance from the root, since if it could be stored contiguously with the value you would not have to go to such length.

I think you could do it "externally", since in this case the rank can be extrapolated from the number of times the comparison predicate is used...

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

It counts the number of tests, but since std::map stops testing as soon as it gets the right key... it should be alright :) Though there is probably some offset to deduce there (1 or 2) to get the rank instead.

If you gave a better definition of rank I may work a bit more but I don't want to spend too much time in the wrong direction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文