c++ - 侵入式 rbtree 中第一个元素的恒定时间测试

标签 c++ boost

如何有效判断元素是否位于侵入集或 rbtree 的开头?我想定义一个简单的函数 prev 返回指向树中前一项的指针,如果没有前一项则返回 nullptr 。类似的 next 函数很容易编写,使用 iterator_to 并与 end() 进行比较。但是,没有等效的 reverse_iterator_to 函数可以让我与 rend() 进行比较。此外,我特别不想与 begin() 进行比较,因为这在红黑树中不是常数时间。

似乎确实可行的一件事是递减迭代器并将其与 end() 进行比较。这在实现中效果很好,但我在文档中找不到对此的支持。在以下最小工作示例中实现 prev 的最佳方法是什么?

#include <iostream>
#include <string>
#include <boost/intrusive/set.hpp>

using namespace std;
using namespace boost::intrusive;

struct foo : set_base_hook<> {
  string name;
  foo(const char *n) : name(n) {}
  friend bool operator<(const foo &a, const foo &b) { return a.name < b.name; }
};

rbtree<foo> tree;

foo *
prev(foo *fp)
{
  auto fi = tree.iterator_to(*fp);
  return --fi == tree.end() ? nullptr : &*fi;
}

int
main()
{
  tree.insert_equal(*new foo{"a"});
  tree.insert_equal(*new foo{"b"});
  tree.insert_equal(*new foo{"c"});
  for (foo *fp = &*tree.find("c"); fp; fp = prev(fp))
    cout << fp->name << endl;
}

更新: 好的,所以我遗漏的是,在 STL 中,begin() 实际上保证是恒定时间的,这可能是 sehe 间接得到的。因此,即使通用红黑树需要 log(n) 时间来找到最小元素,STL 映射却不需要——需要 STL std::map 实现来缓存第一个元素。我认为 sehe 的意思是,即使没有记录 boost,也可以公平地假设 boost::intrusive 容器的行为有点像 STL 容器。鉴于该假设,完全可以说:

foo *
prev(foo *fp)
{
  auto fi = tree.iterator_to(*fp);
  return fi == tree.begin() ? nullptr : &*--fi;
}

因为与 tree.begin() 的比较应该不会太昂贵。

最佳答案

你可以从 iterator_to 得到反向迭代器.

Also, note that there is rbtree<>::container_from_iterator(iterator it) so you don't have to have a "global" state for your prev function.


您只需创建相应的 reverse_iterator 即可。您必须 +1 迭代器才能获得预期的地址: enter image description here

所以我对此的看法是(好处:没有内存泄漏):

Live On Coliru

#include <boost/intrusive/set.hpp>
#include <iostream>
#include <string>
#include <vector>

using namespace boost::intrusive;

struct foo : set_base_hook<> {
    std::string name;
    foo(char const* n) : name(n) {}

    bool operator<(const foo &b) const { return name < b.name; }
};

int main()
{
    std::vector<foo> v;
    v.emplace_back("a");
    v.emplace_back("b");
    v.emplace_back("c");

    using Tree = rbtree<foo>;

    Tree tree;
    tree.insert_unique(v.begin(), v.end());

    for (auto key : { "a", "b", "c", "missing" })
    {
        std::cout << "\nusing key '" << key << "': ";
        auto start = tree.iterator_to(*tree.find(key));

        if (start != tree.end()) {
            for (auto it = Tree::reverse_iterator(++start); it != tree.rend(); ++it)
                std::cout << it->name << " ";
        }
    }
}

哪个打印

using key 'a': a 
using key 'b': b a 
using key 'c': c b a 
using key 'missing': 

关于c++ - 侵入式 rbtree 中第一个元素的恒定时间测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30494398/

相关文章:

c++ - 如果应用程序以 CTRL_CLOSE_EVENT 退出,则 boost::log add_file_log 不写入

c++ - OpenCV 和 Boost 文件系统之间的冲突

c++ - 为什么下面的类模板匹配不二义?

c++ - 如何将信息附加到类层次结构?

c++ - 将 QProcess 输出读取到字符串

c++ - 如何使用变体创建几何体

c++ - 使用 boost property tree 编写比简单的 xml 更复杂

c++ - STL 算法和并发编程

c++ - 数组元素到可变参数模板参数

c++ - boost 图形库 - 顶点颜色和 graphviz 输出的最小示例