Quadtree移动存储点

时间:2012-10-10 18:24:46

标签: c++ data-structures quadtree

我使用四叉树作为数据结构来存储点。因为我需要快速找到某个区域内的所有点。

但是我需要提出要点。在我的C ++程序中。由于移动发生在所有点上,但是对于不同方向的每个点,我当前都会破坏我的四叉树并重建它,这会导致大量的分配和删除。

因此,我的问题是这种问题有更好的数据结构吗?

我有以下要求: 我有n分。

我需要快速了解某个特定区域内的所有点。使用我的四叉树这是关于O(log(n))。然而,该操作被称为m次,其中m> 1。因此,它约为O(m * log(n))。

我需要提出所有要点。目前这大约是O(n * logn)。此方法仅对所有m调用一次。

但是我觉得这个解决方案目前还不尽如人意。因为我总是销毁我的四叉树并重建它,这会因分配而导致开销。

更新 这些要点不是均匀分布的。有些位置是密集的,有些位置的位置很少。

这是一些简化的代码。这里存储指针的代码:

class Point
{
    public:
    Point(double x, double y):x(x),y(y){};

    void movePoint(double ux, double uy);

    double x;
    double y;
};

这是四叉树的接口

class QuadTree
{
public:
    QuadTree(double north, double west, double south, double east,
             int maxItems);

    //inserts a point into the tree runs in log(n)
    bool put(Point* pt);
    // returns all point in the rectange defined by the four variables runs in log(n)
    std::vector<Point*> get(double north, double west, double south, double east);
    // deletes everything in the quad tree
    void clear();

private:

    QuadTreeNode* top_=nullptr;

};

这里是QuadTreeNode与get和put方法实现的接口,用于显示Point的存储方式。

class QuadTreeNode
{
public:

    QuadTreeNode(double north, double west, double south, double east,
                 int maximumItems);

    ~QuadTreeNode();

    //split the node if to much items are stored.
    void split();
    //returns the children of the node
    QuadTreeNode* getChild(double x, double y);

    bool put(Point* leaf){
      if (children_ == nullptr) {
        items_.push_back(leaf);

        if (items_.size() > maxItems_)
            split();
        return true;
      } else {
        QuadTreeNode* node = getChild(leaf->getX(), leaf->getY());
        if (node != nullptr) {
            return node->put(leaf);
        }
       }
      return false;
    }

    std::vector<Point*> QuadTreeNode::get(QuadRectangle rect, std::vector<Point*>& vector) {
      if (children_ == nullptr) {
        for (Point* pt : items_) {
            if (rect.pointWithinBounds(pt->getX(),pt->getY())) {
                vector.push_back(pt);
            }
        }
      } else {
        for (QuadTreeNode* child : *children_) {
            if (child->bounds_.within(rect)) {
                child->get(rect, vector);
            }
        }
      }
      return vector;
}

    std::vector<Point*> items_;

    unsigned int maxItems_;

    std::array<QuadTreeNode*,4>* children_ = nullptr;

    QuadRectangle bounds_;    
};

1 个答案:

答案 0 :(得分:1)

想到的一些想法:

  1. 对于每个移动的点,检查它是否移出边界矩形(bounds_)。如果是,请将其从树中删除。移动所有点后,将它们插入同一树中,或插入另一棵树中。每隔一段时间(例如,当另一棵树的大小变成主树的1/10时),重建一切。
  2. 分割节点时,您可能会为每个子注释中的点计算一个边界矩形。在这样做时,允许一些边距进入边界,因此可以将每个点移动几次,而不会超出范围。
  3. 这些想法无助于复杂性(它仍然是O(n * log(n)),但可能会因某些因素而提高速度。