好久好久没更过了,因为入坑了一本天书的缘故,有一些比较特别的数据结构需要学一下,第一个就是这个四叉树,工作占的时间太多了,只能用剩下的时间来学一学了,话不多说,先来介绍一下基本的概念:
我们这里的四叉树指的是满四叉树,也就是每个节点要么有四个孩子节点,要么没有孩子节点,它在二维空间中可以表示对一个正方形进行四个象限的分割,从右上,左上,左下,右下这四个方向可以依次表示为第一象限,第二象限,第三象限和第四象限,如图:其中,根节点表示大的正方形,根节点下的四个节点分别表示对应的四个分割出来的正方形。
这里,还有三个关于四叉树的定理:
1.平面中一组点P的四叉树的深度最多为log(s/c) + 3/2,其中c是P中任意两个点之间的最小距离,s是正方形的边长。
2.存储了一组n个点,深度为d的四叉树,具有O(d + 1)个结点并且可以在O((d+1)n)时间内构造。
3.设T为深度为d的四叉树,如上所述,T中给定节点v在给定方向上的邻居可以在O(d+1)时间内找到。
定理为啥成立,我也不知道,一本很阴间的书上写的。 定义和定理结束了,下面是代码,我用C++实现的:
关于四叉树的类定义:(重载的运算符和构造函数,析构函数,拷贝构造函数方法体都放在类里了,自定义的函数方法体放在了类外)
对于四叉树的每个节点,我定义它有一个矩形区域,有一个链表pointList表示在这个矩形区域内的点,以及四个指向孩子节点的指针和指向父节点的指针,还有一系列函数。书上虽然是按正方形讲的,但是,矩形好像更加准确,所以我下边都写的矩形。
class QuadTree
{
public:
//四叉树对应的矩形区域。
Rectangle treeRec;
QuadTree(){}
QuadTree(Rectangle treeRec){this->treeRec = treeRec;}
QuadTree(Rectangle treeRec,PointList* pointList)
{
this->treeRec = treeRec;
this->pointList = pointList;
}
//对于用这个构造函数的形式创建的四叉树,是在矩形区域分裂得到子节点的时候用到的,因此,对于父节点矩形区域中的点链表(不带头节点),需要分给子节点。
QuadTree(Rectangle treeRec,QuadTree* parent)
{
this->treeRec = treeRec;
this->pointList = pointList;
this->parent = parent;
PointList* parentList = parent->pointList;
pointList = new PointList();
Point p(-1,-1);
pointList->point = p;
//cout<<pointList->point.x <<endl;
pointList->next = NULL;
while(parentList!=NULL)
{
if(treeRec.IsInRectangle(parentList->point))
{
if(pointList->point.x == -1)
{
pointList->point = parentList->point;
//cout<<1<<endl;
}
else
{
pointList->Insert(parentList->point);
}
}
parentList = parentList->next;
}
}
~QuadTree()
{
delete rightTopTree;
delete leftTopTree;
delete leftBottomTree;
delete rightBottomTree;
delete pointList;
delete this;
}
QuadTree* rightTopTree;
QuadTree* leftTopTree;
QuadTree* leftBottomTree;
QuadTree* rightBottomTree;
QuadTree* parent;
//这个表示一个点的链表,表示这个父节点的矩形区域中有这些点。
PointList* pointList;
//剩下的函数我会在代码中说明,读者读到这只需要根据它的名字明白它是干啥的就行了。
void CreateChildren();
Rectangle* RectangleSearch(Point point,Rectangle* rec,QuadTree* root);
bool PointSearch(Point point);
bool PointDelete(Point point,QuadTree* tar);
bool RectangleDelete(Rectangle rec,QuadTree* tar);
void DeleteAllChildren(QuadTree* tar);
QuadTree* FindNeibor(Direction dir,QuadTree* tar,QuadTree* parent);
};
下面是矩形和点,以及点链表的定义,没啥好说的:
class Point
{
public:
int x;
int y;
Point(const Point &point)
{
x = point.x;
y = point.y;
}
Point(int x,int y)
{
this->x = x;
this->y = y;
}
Point()
{
}
~Point(){}
bool operator==(Point& other)
{
return this->x == other.x && this->y == other.y;
}
bool operator!=(Point& other)
{
return this->x != other.x || this->y != other.y;
}
Point operator=(Point& other)
{
this->x = other.x;
this->y = other.y;
return *this;
}
};
class PointList
{
public:
Point point;
PointList* next;
void Insert(Point point);
friend bool Delete(PointList*& tar, Point point);
//Fix表示的是改
void Fix(Point point,Point tar);
bool Search(Point point);
};
class Rectangle
{
public:
int xMin;
int xMax;
int yMin;
int yMax;
Rectangle(int xMin,int xMax,int yMin,int yMax)
{
this->xMin = xMin;
this->xMax = xMax;
this->yMin = yMin;
this->yMax = yMax;
}
bool operator==(const Rectangle& other)
{
return this->xMin == other.xMin && this->xMax == other.xMax && this->yMin == other.yMin && this->yMax == other.yMax;
}
bool operator!=(const Rectangle& other)
{
return !(this->xMin == other.xMin && this->xMax == other.xMax && this->yMin == other.yMin && this->yMax == other.yM