线性四叉树的实现
1)线性四叉树只存储最后的叶节点信息,包括叶节点的位置,大小和深度(根据数组下标可以直接得到)。
2)使用节点引用类型的vector容器表示一颗完全四叉树。
3) 完全四叉树的父节点数组下标为i时,对应的子节点下标为4*i+num,num∈{1,2,3,4}。
不足:
1.为了通过数组下标明确父节点与子节点的关系,采用的是完全四叉树的结构,由于地理空间对象可能分布不均衡,这样会导致四叉树生成一棵极为不平衡的树,也会造成树结构的不平衡以及存储空间的极大浪费。
2.为了判断是否是叶子结点,在数组声明时,将数组元素的leaf成员声明为true,但是在插入数据之前并不知道树的深度,需要预留大量空间,并对数组中所有元素赋初值,导致时间和vector空间的浪费。
3.存储非叶子节点的vector空间浪费。
#include <iostream>
#include <vector>
#include<cstdlib>
#include<math.h>
#include <time.h>
#include<fstream>
const int MAX_NUM=100;
using namespace std;
struct Region;
//最小外接矩形
struct Region {
int right;
int left;
int up;
int bottom;
};
//点
struct Point {
float x;
float y;
}p;
//定义四叉树的节点
struct QuadtNode {
vector<Point> list;//存储四叉树该节点的所有坐标
int depth;//四叉树的深度
int size;//记录节点数,最大值MAX_NUM
bool leaf;//记录是否为叶子节点
Region region;
};
vector<Point> xy;
vector<Point> a_xy;
vector< QuadtNode> q;
vector< QuadtNode> &quadtree= q;//节点的vector容器来表示一颗四叉树
void creatQuadtree();//创建空四叉树
void insertQuadtree(long int , Point );//插入一个坐标
void regionSet(QuadtNode node, int b, int u, int l, int r);//更新MBR
void splitNode(long int index);//节点分裂
void queryEle(int index, Point ele);//点查询
void out();//文件输出
int main()
{
long int i;
quadtree.resize(100000);
// cout << quadtree.capacity();
for (i = 0; i < 100000; i++) {
quadtree[i].leaf = 1;
quadtree[i].size = 0;
//cout<<quadtree[i].leaf;
}
//creatQuadtree();
//for (vector<QuadtNode>::iterator i = quadtree.begin(); i < quadtree.end(); i++) {
Point p;
srand((int)time(NULL));//随机数
for (int i = 0; i < 1000; i++) {
p.y = (float)(rand() % 360 - 180 + (float)(rand() % 1000) / 1000);
p.x = (float)(rand() % 180 - 90 + (float)(rand() % 1000) / 1000);
insertQuadtree(0, p);
a_xy.push_back(p);
}
//for (vector<QuadtNode>::iterator it = quadtree.begin(); it < quadtree.end(); it++) {
// if ((*it).leaf == 1&&(*it).leaf!=NULL)
// for (vector<Point>::iterator count = (*it).list.begin(); count < (*it).list.end(); count++) {
// cout << (*count).x << "," << (*count).y << endl;
// }
//}
Point ele;
ele.x = -24;
ele.y = -20;
queryEle(0, ele);
out();
}
//查询
void queryEle( int index, Point ele) {
if (quadtree[index].leaf == 1) {
printf("附近点有%d个,分别是:\n", quadtree[index].size);
for (int j = 0; j < quadtree[index].size; j++) {
printf("%f,%f\n", quadtree[index].list[j].x, quadtree[index].list[j].y);
xy.push_back(quadtree[index].list[j]);
}
return;
}
double mid_vertical = (quadtree[index].region.up + quadtree[index].region.bottom) / 2;
double mid_horizontal = (quadtree[index].region.left + quadtree[index].region.right) / 2;
if (ele.x > mid_vertical) {
if (ele.y > mid_horizontal) {
queryEle(4 * index + 1, ele);
}
else {
queryEle(4 * index + 4, ele);
}
}
else {
if (ele.y > mid_horizontal) {
queryEle(4 * index + 2, ele);
}
else {
queryEle(4 * index + 3, ele);
}
}
}
//创建空四叉树
void creatQuadtree()
{
QuadtNode node;
p.x = 0;
p.y = 0;
node.list.push_back(p);
node.size = 0;
node.depth = 0;
node.region.bottom = -90;
node.region.up = 90;
node.region.left = -180;
node.region.right = 180;
node.leaf = 1;
quadtree.push_back(node);
}
//插入一个点,index是当前节点的下标
void insertQuadtree(long int index, Point p)
{
if (quadtree[index].leaf==true ) {//如果当前节点是叶子节点
if ((quadtree[index].size + 1 )> MAX_NUM){//节点数据已满
splitNode(index);//节点分裂
insertQuadtree(index, p);
}
else {
quadtree[index].list.push_back(p);//节点未满则插入点坐标
quadtree[index].size++; //更新节点所包含点数
}
return;
}
//进入四分区域
double mid_vertical = (quadtree[index].region.up + quadtree[index].region.bottom) / 2;
double mid_horizontal = (quadtree[index].region.left + quadtree[index].region.right) / 2;
if (p.x > mid_vertical) {
if (p.y > mid_horizontal) {
insertQuadtree(4 * index + 1, p);//
}
else {
insertQuadtree(4 * index + 4, p);
}
}
else {
if (p.y > mid_horizontal) {
insertQuadtree(4 * index + 2, p);
}
else {
insertQuadtree(4 * index + 3, p);
}
}
}
//更新MBR
void regionSet(QuadtNode node,int b,int u,int l,int r )
{
node.region.bottom = b;
node.region.up = u;
node.region.left = l;
node.region.right = r;
}
//分裂节点
void splitNode(long int index) {
double mid_vertical = (quadtree[index].region.up + quadtree[index].region.bottom) / 2;
double mid_horizontal = (quadtree[index].region.left + quadtree[index].region.right) / 2;
quadtree[index].leaf = 0;
regionSet(quadtree[4 * index + 1], mid_vertical, quadtree[4 * index + 1].region.up, mid_horizontal, quadtree[4 * index + 1].region.right);
regionSet(quadtree[4 * index + 2], mid_vertical, quadtree[4 * index + 2].region.up, quadtree[4*index+2].region.left, mid_horizontal);
regionSet(quadtree[4 * index + 3], quadtree[4 * index + 3].region.bottom, mid_vertical, mid_horizontal, quadtree[4 * index + 3].region.right);
regionSet(quadtree[4 * index + 4], quadtree[4 * index + 4].region.bottom, mid_vertical, quadtree[4 * index + 4].region.left, mid_horizontal);
for (int i = 0; i < quadtree[index].size; i++) {
insertQuadtree(index, quadtree[index].list[i]);
quadtree[index].size--;
}
}
//文件输出
void out() {
fstream ofs1;
int i, j;
ofs1.open("XY.txt", ios::out);
for (i = 0; i < xy.size(); i++) {
ofs1 << xy[i].x << " ";
ofs1 << xy[i].y << endl;
}
fstream ofs2;
ofs2.open("allXY.txt", ios::out);
for (i = 0; i < a_xy.size(); i++) {
ofs2 << a_xy[i].x << " ";
ofs2 << a_xy[i].y << endl;
}
}## 标题