四叉树是用于有效存储二维空间上点数据的树。在这棵树中,每个节点最多具有四个子节点。
我们可以使用以下步骤从二维区域构造四叉树:
- 将当前的二维空间划分为四个框。
- 如果一个盒子中包含一个或多个点,则创建一个子对象,在其中存储盒子的二维空间
- 如果一个框不包含任何点,则不要为其创建子级
- 为每个孩子递归。
四叉树用于图像压缩,其中每个节点包含其每个子节点的平均颜色。您在树中遍历的深度越深,图像的细节越多。
四叉树还用于在二维区域中搜索节点。例如,如果您想找到最接近给定坐标的点,则可以使用四叉树来完成。
插入函数
插入功能用于将节点插入现有的四叉树。此函数首先检查给定的节点是否在当前四边形的边界内。如果不是,那么我们立即停止插入。如果它在边界内,则根据其位置选择适当的子级以包含此节点。
此函数为O(Log N),其中N为距离的大小。
搜索函数
搜索函数用于在给定的四边形中定位节点。还可以对其进行修改,以将最近的节点返回给定点。通过获取给定点,与子四边形的边界进行比较并递归,可以实现此函数。
此函数为O(Log N),其中N为距离的大小。
下面给出的程序演示了在四叉树中存储节点。
// C++ Implementation of Quad Tree
#include
#include
using namespace std;
// Used to hold details of a point
struct Point
{
int x;
int y;
Point(int _x, int _y)
{
x = _x;
y = _y;
}
Point()
{
x = 0;
y = 0;
}
};
// The objects that we want stored in the quadtree
struct Node
{
Point pos;
int data;
Node(Point _pos, int _data)
{
pos = _pos;
data = _data;
}
Node()
{
data = 0;
}
};
// The main quadtree class
class Quad
{
// Hold details of the boundary of this node
Point topLeft;
Point botRight;
// Contains details of node
Node *n;
// Children of this tree
Quad *topLeftTree;
Quad *topRightTree;
Quad *botLeftTree;
Quad *botRightTree;
public:
Quad()
{
topLeft = Point(0, 0);
botRight = Point(0, 0);
n = NULL;
topLeftTree = NULL;
topRightTree = NULL;
botLeftTree = NULL;
botRightTree = NULL;
}
Quad(Point topL, Point botR)
{
n = NULL;
topLeftTree = NULL;
topRightTree = NULL;
botLeftTree = NULL;
botRightTree = NULL;
topLeft = topL;
botRight = botR;
}
void insert(Node*);
Node* search(Point);
bool inBoundary(Point);
};
// Insert a node into the quadtree
void Quad::insert(Node *node)
{
if (node == NULL)
return;
// Current quad cannot contain it
if (!inBoundary(node->pos))
return;
// We are at a quad of unit area
// We cannot subdivide this quad further
if (abs(topLeft.x - botRight.x) <= 1 &&
abs(topLeft.y - botRight.y) <= 1)
{
if (n == NULL)
n = node;
return;
}
if ((topLeft.x + botRight.x) / 2 >= node->pos.x)
{
// Indicates topLeftTree
if ((topLeft.y + botRight.y) / 2 >= node->pos.y)
{
if (topLeftTree == NULL)
topLeftTree = new Quad(
Point(topLeft.x, topLeft.y),
Point((topLeft.x + botRight.x) / 2,
(topLeft.y + botRight.y) / 2));
topLeftTree->insert(node);
}
// Indicates botLeftTree
else
{
if (botLeftTree == NULL)
botLeftTree = new Quad(
Point(topLeft.x,
(topLeft.y + botRight.y) / 2),
Point((topLeft.x + botRight.x) / 2,
botRight.y));
botLeftTree->insert(node);
}
}
else
{
// Indicates topRightTree
if ((topLeft.y + botRight.y) / 2 >= node->pos.y)
{
if (topRightTree == NULL)
topRightTree = new Quad(
Point((topLeft.x + botRight.x) / 2,
topLeft.y),
Point(botRight.x,
(topLeft.y + botRight.y) / 2));
topRightTree->insert(node);
}
// Indicates botRightTree
else
{
if (botRightTree == NULL)
botRightTree = new Quad(
Point((topLeft.x + botRight.x) / 2,
(topLeft.y + botRight.y) / 2),
Point(botRight.x, botRight.y));
botRightTree->insert(node);
}
}
}
// Find a node in a quadtree
Node* Quad::search(Point p)
{
// Current quad cannot contain it
if (!inBoundary(p))
return NULL;
// We are at a quad of unit length
// We cannot subdivide this quad further
if (n != NULL)
return n;
if ((topLeft.x + botRight.x) / 2 >= p.x)
{
// Indicates topLeftTree
if ((topLeft.y + botRight.y) / 2 >= p.y)
{
if (topLeftTree == NULL)
return NULL;
return topLeftTree->search(p);
}
// Indicates botLeftTree
else
{
if (botLeftTree == NULL)
return NULL;
return botLeftTree->search(p);
}
}
else
{
// Indicates topRightTree
if ((topLeft.y + botRight.y) / 2 >= p.y)
{
if (topRightTree == NULL)
return NULL;
return topRightTree->search(p);
}
// Indicates botRightTree
else
{
if (botRightTree == NULL)
return NULL;
return botRightTree->search(p);
}
}
};
// Check if current quadtree contains the point
bool Quad::inBoundary(Point p)
{
return (p.x >= topLeft.x &&
p.x <= botRight.x &&
p.y >= topLeft.y &&
p.y <= botRight.y);
}
// Driver program
int main()
{
Quad center(Point(0, 0), Point(8, 8));
Node a(Point(1, 1), 1);
Node b(Point(2, 5), 2);
Node c(Point(7, 6), 3);
center.insert(&a);
center.insert(&b);
center.insert(&c);
cout << "Node a: " <<
center.search(Point(1, 1))->data << "\n";
cout << "Node b: " <<
center.search(Point(2, 5))->data << "\n";
cout << "Node c: " <<
center.search(Point(7, 6))->data << "\n";
cout << "Non-existing node: "
<< center.search(Point(5, 5));
return 0;
}
输出:
Node a: 1
Node b: 2
Node c: 3
Non-existing node: 0
锻炼:
实现四叉树,该四叉树将4个最接近的节点返回给定点。
其他参考:
http://jimkang.com/quadtreevis/
https://zh.wikipedia.org/wiki/四树