Boost Intrusive /二进制搜索树

时间:2013-05-22 15:11:04

标签: c++ boost tree avl-tree voronoi

我正在寻找一个Voronoi曲面细分算法的二元搜索树(Fortune的算法;本身就是一个非常重要的任务,也就是这个问题),所以当然,我想我会看看Boost。

Boost有Intrusive头文件,它似乎包含大量BST(例如AVL,Splay树和Scapegoat树 - 哈,我必须在那里确定那个名字!)并且最初视线看起来就像我需要的那样。

1:我错过了什么或者无法直接访问树的根节点?

2: AVL树是否适合财富算法海滩线结构?

该死的,我觉得这很容易。

更新:也许最好说明我的目标:我想实施抛物线搜索,它是财富算法的一部分,检测新网站的部分,我们需要直接在头顶上找到抛物线。我以为我会从根开始遍历树,以便找到正确的弧。

4 个答案:

答案 0 :(得分:3)

 iterator begin();
 const_iterator begin() const;
 const_iterator cbegin() const;

基于文档,有点不清楚,但看起来begin()将返回第一个头节点(也称为根节点)。

http://www.dcs.gla.ac.uk/~samm/trees.html

<强>更新

 #include <iostream>
 #include <algorithm>
 #include <boost/intrusive/rbtree.hpp>

 using namespace boost::intrusive;

 struct X  : public set_base_hook<optimize_size<true> > {
    X(int x) : _x{x} { }

    int _x;

    friend inline std::ostream& operator<<(std::ostream&, const X&);
    friend bool operator<(const X&, const X&);
    friend bool operator>(const X&, const X&);
    friend bool operator==(const X&, const X&);
 };

 std::ostream& operator<<( std::ostream& os, const X& x) {
    os << x._x;
    return os;
 }

 bool operator<(const X&  lhs, const X& rhs) { return lhs._x < rhs._x; }
 bool operator>(const X&  lhs, const X& rhs) { return lhs._x > rhs._x; }
 bool operator==(const X& lhs, const X& rhs) { return lhs._x == rhs._x; }

 int main()
 {
    typedef rbtree<X> tree_t;

    tree_t tree;
    X x0(0);
    X x1(1);
    X x2(2);

    /*! Output is the same for the following
    * X x1(1);
    * X x0(0);
    * X x2(2);
    */

    tree.insert_unique(x1);
    tree.insert_unique(x0);
    tree.insert_unique(x2);

    std::for_each(
          tree.begin(), tree.end(),
          [](const X& xx) { std::cout << "x: " << xx << std::endl; });
 }

输出

  

x:0   x:1   x:2

我注意到push_back / push_front没有调用树重新排序。也许我在文档中错过了它。

答案 1 :(得分:1)

最后我实现了自己的AVL树。 Voronoi算法的复杂性似乎要求它,并且Boost版本无法访问节点,无论如何(如果我错了,请指出它;考虑到Boost的默默无闻,它是可能的)。

AVL树似乎完美地完成了这项工作。

答案 2 :(得分:0)

实际上查找root比听起来容易。

首先,你必须编写通常的东西来使用boost :: intrusive之类的钩子等等。

boost::intrusive::avltree<Object> avl;

如果要在任何boost :: intrusive中查找节点,则必须使用find()。 现在,find()函数需要一个overloaded()运算符,它基本上检查$ a> b $或$ b&lt; a $(非常类似于strcmp的布尔输出),您希望此运算符在根节点处失败,因此它将返回根作为结果。这样做的一种方法是

class RootComp{
 bool operator () (const Object &a, const int b) const {
        return false;
    }

    bool operator () (int b, const Object &a) const{
        return false;
    }
};

然后使用find()很简单:

 int data=0;
 boost::intrusive::avltree<Object>::iterator it = avl.find(data, RootComp());
    if( it != avl.end() ){
        //*it is the root
    }else{
       // the tree is empty
    }

答案 3 :(得分:0)

Boost.Intrusive树状容器有一个root()成员,如果没有根节点,则返回根节点或end()的迭代器。这些功能很久以前就已经发生了。以下提交:

https://github.com/boostorg/intrusive/commit/6d38384e369697894bb71fb81132ad60b796c70c

记录这些功能,因此它们现在是正式的。以下代码显示了如何使用它:

#include <boost/intrusive/set.hpp>
#include <cassert>

using namespace boost::intrusive;

struct MyClass : public set_base_hook<>
{
   friend bool operator<(const MyClass&, const MyClass&)
   {  return true;   }
};

int main()
{
   set<MyClass> set;
   //end() is returned when the tree is empty
   assert(set.root()  == set.end() );

   //insert myobject, must be root
   MyClass myobject;
   set.insert(myobject);
   assert(&*set.root() == &myobject);

   //erase and check root is again end()
   set.erase(set.root());
   assert(set.croot() == set.cend());

   return 0;   
}