线性四叉树的实现C++

线性四叉树的实现

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;
	}

}## 标题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值