• C++实现四叉树索引


    3.四叉树索引实现

    3.1指针实现

    四叉树索引的基本思想是将地理空间递归划分为不同层次的树结构。它将已知范围的空间划分为四个相等的子空间,如此递归下去,直至树的层次达到一定深度或者满足某种要求后停止分割。四叉树的结构比较简单,并且当空间数据分布比较均匀时,具有比较高的空间数据插入和查询效率。这里介绍的四叉树结构中,所有的点位置信息都存储在叶子节点上,中间节点以及根结点不存储点信息。

    为了快速检索点,设计了如下的数据结构来支持四叉树的操作。

    1. 最小外包矩形数据结构:定义了一个矩形区域的四条边的坐标范围
     //矩形区域
    struct Region 
    {
         double up;  //上边界
         double bottom; //下边界
         double left;  //左边界
         double right;  //右边界
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 点数据结构:定义了点的x和y坐标
    //点结构体
    struct ElePoint 
    {
         double lng;  //x坐标
         double lat;  //y坐标
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.四叉树结点数据结构:四叉树结点是四叉树结构的主要组成部分,主要用于存储点的最小外包矩形,深度,子节点指针等,也是四叉树算法操作的主要部分。

    //四叉树结点
    struct QuadTreeNode
    {
      int depth;  //结点的深度
      int is_leaf;  //是否是叶子节点
       struct Region region;  //区域范围
       struct QuadTreeNode *LU; //左上子节点指针
       struct QuadTreeNode *LB;  //左下子节点指针
       struct QuadTreeNode *RU;  //右上子节点指针
       struct QuadTreeNode *RB;  //右下子节点指针
       int ele_num;   //矩形区域中位置点数
       struct ElePoint *ele_list[MAX_ELE_NUM];  //矩形区域中位置点列表
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    四叉树的主要操作:

    1. 插入元素:将元素插入到叶子节点中,其步骤如下:

    (1)判断结点是否已经分裂,已分裂的选择合适的子节点,进行插入;

    (2)未分裂的查看是否过载,过载的分裂结点,重新插入;

    (3)未过载的直接插入。

    示例代码如下:

    void insertEle(QuadTreeNode *node, ElePoint ele)
    {
    	//是叶子结点
    	if (1 == node->is_leaf) 
    	{
    		if (node->ele_num + 1 > MAX_ELE_NUM) 
    		{
    			splitNode(node);
    
    			//分裂后的 node 不是叶子节点,所以新插入的元素会插入到 node 的子节点上
    			insertEle(node, ele);  //将新插入的元素插入到node的子节点上
    		}
    		else 
    		{
    			ElePoint *ele_ptr = ( ElePoint *) malloc(sizeof(ElePoint));
    			ele_ptr->lat = ele.lat;
    			ele_ptr->lng = ele.lng;
    
    			//将新插入的点加入到父节点的位置点列表中
    			node->ele_list[node->ele_num] = ele_ptr;
    			node->ele_num++;
    		}
    
    		return;
    	}
    
    	//不是叶子结点
    	double mid_vertical = (node->region.up + node->region.bottom) / 2;
    	double mid_horizontal = (node->region.left + node->region.right) / 2;
    	if (ele.lat > mid_vertical)
    	{
    		if (ele.lng > mid_horizontal) 
    		{
    			insertEle(node->RU, ele);
    		}
    		else
    		{
    			insertEle(node->LU, ele);
    		}
    	}
    	else 
    	{
    		if (ele.lng > mid_horizontal)
    		{
    			insertEle(node->RB, ele);
    		}
    		else
    		{
    			insertEle(node->LB, ele);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    2.分裂结点:对父节点进行分裂,分成四个子区域,其步骤如下:

    (1)通过父节点获取子节点的深度和范围;

    (2)父节点分裂出四个子节点;

    (3)将父节点的元素插入到子节点上,然后释放父节点元素空间

    (4)父节点的位置点数-1

    示例代码如下:

    void splitNode(struct QuadTreeNode *node)
    {
    	double mid_vertical = (node->region.up + node->region.bottom) / 2;  //垂直放向的中间线
    	double mid_horizontal = (node->region.left + node->region.right) / 2;  //水平方向的中间线
    
    	node->is_leaf = 0;
    	//生成四个孩子结点
    	node->RU = createChildNode(node, mid_vertical, node->region.up, mid_horizontal, node->region.right);
    	node->LU = createChildNode(node, mid_vertical, node->region.up, node->region.left, mid_horizontal);
    	node->RB = createChildNode(node, node->region.bottom, mid_vertical, mid_horizontal, node->region.right);
    	node->LB = createChildNode(node, node->region.bottom, mid_vertical, node->region.left, mid_horizontal);
    
    	for (int i = 0; i < node->ele_num; i++) 
    	{
    		//此时插入的时候,node不是叶子节点,此时执行 insert 函数,会将元素插入到孩子节点上
    		insertEle(node, *node->ele_list[i]);   // 将父节点元素 插入到子节点
    		free(node->ele_list[i]);   //释放父节点元素
    		node->ele_num--;     //每插入一个元素,父节点的元素数-1
    	}
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    3.查询:输入一个检索点,然后输出与这个点在同一个四叉树结点中的所有点,步骤如下:

    (1)先判断该点是否是叶子节点;

    (2)是叶子结点直接输出该点所在区域的周边点;

    (3)不是叶子结点,递归搜索其子节点;

    示例代码如下:

    void queryEle(struct QuadTreeNode node, struct ElePoint ele) 
    {
    	//是叶子结点
    	if (node.is_leaf == 1) 
    	{
    		cout << "附近点有" << node.ele_num << "个,分别是:" << endl;
    		for (int j = 0; j < node.ele_num; j++)
    		{
    			cout << "(" << node.ele_list[j]->lng << "," << node.ele_list[j]->lat << ")";
    		}
    		return;
    	}
    
    	//不是叶子节点
    	double mid_vertical = (node.region.up + node.region.bottom) / 2;
    	double mid_horizontal = (node.region.left + node.region.right) / 2;
    
    	if (ele.lat > mid_vertical) 
    	{
    		if (ele.lng > mid_horizontal) 
    		{
    			queryEle(*node.RU, ele);
    		}
    		else 
    		{
    			queryEle(*node.LU, ele);
    		}
    	}
    	else
    	{
    		if (ele.lng > mid_horizontal)
    		{
    			queryEle(*node.RB, ele);
    		}
    		else
    		{
    			queryEle(*node.LB, ele);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    任意区域查询:

    //任意区域查询
    void queryArea(QuadTreeNode *node, Region *region)
    {	//是叶子节点
    	if (node->is_leaf == 1)
    	{	
    		//遍历叶子节点中的所有点
    		for (int i = 0; i < node->ele_num; i++) 
    		{	
    			//如果叶子节点中有点在该矩形区域中,就输出该点坐标
    			if (node->ele_list[i]->lng >= region->left &&
    				node->ele_list[i]->lng <= region->right &&
    				node->ele_list[i]->lat >= region->bottom &&
    				node->ele_list[i]->lat <= region->up) 
    			{
    				cout << "(" << node->ele_list[i]->lng << "," << node->ele_list[i]->lat << ") ";
    			}
    		}
    		cout << endl;
    		return;
    	}
    	
    	//不是叶子结点 , 递归查找与矩形区域有交集的叶子结点
    	double mid_vertical = (node->region.up + node->region.bottom) / 2;
    	double mid_horizontal = (node->region.left + node->region.right) / 2;
    
    	//讨论矩形区域的9种分布情况
    	if (region->bottom > mid_vertical){
    		if (region->left > mid_horizontal){
    			//如果矩形区域的下边界大,左边界大,就在右上区域查询
    			queryArea(node->RU, region);
    		}
    		else if (region->right < mid_horizontal){
    			queryArea(node->LU, region);
    		}
    		else{
    			//将该矩形区域分成两块,逐块递归判断其所属的子区域
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { region->bottom,region->up,region->left,mid_horizontal };
    			queryArea(node->LU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,region->up,mid_horizontal,region->right };
    			queryArea(node->RU, region2);
    		}
    	}
    
    	else if (region->up < mid_vertical){
    		if (region->right < mid_horizontal){
    			queryArea(node->LB, region);
    		}
    		else if (region->left > mid_horizontal){
    			queryArea(node->RB, region);
    		}
    		else{
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { region->bottom, region->up,region->left,mid_horizontal };
    			queryArea(node->LB, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,region->up,mid_horizontal,region->right };
    			queryArea(node->RB, region2);
    		}
    	}
    
    	else{
    		if (region->right < mid_horizontal){
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { mid_vertical,region->up,region->left,region->right };
    			queryArea(node->LU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,mid_vertical,region->left,region->right };
    			queryArea(node->LB, region2);
    
    		}
    		else if (region->left > mid_horizontal)	{
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { mid_vertical,region->up,region->left,region->right };
    			queryArea(node->RU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,mid_vertical,region->left,region->right };
    			queryArea(node->RB, region2);
    		}
    		else {
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { mid_vertical,region->up,region->left,mid_horizontal };
    			queryArea(node->LU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { mid_vertical,region->up,mid_horizontal,region->right };
    			queryArea(node->RU, region2);
    
    			Region *region3 = (Region *)malloc(sizeof(Region));
    			*region3 = { region->bottom,mid_vertical,region->left,mid_horizontal };
    			queryArea(node->LB, region3);
    
    			Region *region4 = (Region *)malloc(sizeof(Region));
    			*region4 = { region->bottom, mid_vertical,mid_horizontal,region->right };
    			queryArea(node->RB, region4);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    完整代码展示:
    #include 
    using namespace std;
    #include 
    #include 
    #include 
    
    #define MAX_ELE_NUM 100   //每块区域的最大点数
    
    #define QUADRANT_RU 1
    #define QUADRANT_LU 2
    #define QUADRANT_LB 3
    #define QUADRANT_RB 4
    
    //矩形区域
    struct Region 
    {
        double bottom;
    	double up;	
    	double left;
    	double right;
    };
    
    
    //点结构体
    struct ElePoint 
    {
    	double lng;   //x坐标
    	double lat;   //y坐标
    };
    
    //四叉树结点
    struct QuadTreeNode
    {
    	int depth;   //结点的深度
    	int is_leaf;   //是否是叶子节点
    	struct Region region;   //区域范围
    	struct QuadTreeNode *LU;  //左上子节点指针
    	struct QuadTreeNode *LB;   //左下子节点指针
    	struct QuadTreeNode *RU;   //右上子节点指针
    	struct QuadTreeNode *RB;   //右下子节点指针
    	int ele_num;     //矩形区域中位置点数
    	struct ElePoint *ele_list[MAX_ELE_NUM];   //矩形区域中位置点列表
    };
    
    //函数声明
    void initNode(QuadTreeNode *node, int depth,  Region region);
    
    void insertEle(QuadTreeNode *node,  ElePoint ele);
    
    void splitNode(QuadTreeNode *node);
    
    void queryEle( QuadTreeNode tree,  ElePoint ele);
    
    void initRegion( Region *region, double up, double bottom, double left, double right);
    
    QuadTreeNode *createChildNode( QuadTreeNode *node, double bottom, double up, double left, double right);
    
    
    
    /**
     * 插入元素
     * 1.判断是否已分裂,已分裂的选择适合的子结点,插入;
     * 2.未分裂的查看是否过载,过载的分裂结点,重新插入;
     * 3.未过载的直接添加
     *
     * @param node
     * @param ele
     * todo 使用元素原地址,避免重新分配内存造成的效率浪费
     */
    void insertEle(QuadTreeNode *node, ElePoint ele)
    {
    	//是叶子结点
    	if (1 == node->is_leaf) 
    	{
    		if (node->ele_num + 1 > MAX_ELE_NUM) 
    		{
    			splitNode(node);
    
    			//分裂后的 node 不是叶子节点,所以新插入的元素会插入到 node 的子节点上
    			insertEle(node, ele);  //将新插入的元素插入到node的子节点上
    		}
    		else 
    		{
    			ElePoint *ele_ptr = ( ElePoint *) malloc(sizeof(ElePoint));
    			ele_ptr->lat = ele.lat;
    			ele_ptr->lng = ele.lng;
    
    			//将新插入的点加入到父节点的位置点列表中
    			node->ele_list[node->ele_num] = ele_ptr;
    			node->ele_num++;
    		}
    
    		return;
    	}
    
    	//不是叶子结点
    	double mid_vertical = (node->region.up + node->region.bottom) / 2;
    	double mid_horizontal = (node->region.left + node->region.right) / 2;
    	if (ele.lat > mid_vertical)
    	{
    		if (ele.lng > mid_horizontal) 
    		{
    			insertEle(node->RU, ele);
    		}
    		else
    		{
    			insertEle(node->LU, ele);
    		}
    	}
    	else 
    	{
    		if (ele.lng > mid_horizontal)
    		{
    			insertEle(node->RB, ele);
    		}
    		else
    		{
    			insertEle(node->LB, ele);
    		}
    	}
    }
    
    /**
     * 分裂结点
     * 1.通过父结点获取子结点的深度和范围
     * 2.生成四个结点,挂载到父结点下
     *
     * @param node
     */
    void splitNode(struct QuadTreeNode *node)
    {
    	double mid_vertical = (node->region.up + node->region.bottom) / 2;  //垂直放向的中间线
    	double mid_horizontal = (node->region.left + node->region.right) / 2; //水平方向的中间线
    
    	node->is_leaf = 0;
        
    	//生成四个孩子结点
    	node->RU = createChildNode(node, mid_vertical, node->region.up, mid_horizontal, node-				>region.right);
    	node->LU = createChildNode(node, mid_vertical, node->region.up, node->region.left, 					mid_horizontal);
    	node->RB = createChildNode(node, node->region.bottom, mid_vertical, mid_horizontal, 				node->region.right);
    	node->LB = createChildNode(node, node->region.bottom, mid_vertical, node-							>region.left, mid_horizontal);
    
    	for (int i = 0; i < node->ele_num; i++) 
    	{
    		//此时插入的时候,node不是叶子节点,此时执行 insert 函数,会将元素插入到孩子节点上
    		insertEle(node, *node->ele_list[i]);   // 将父节点元素 插入到子节点
    		free(node->ele_list[i]);   //释放父节点元素
            
    		//node->ele_num--;//这里每次循环的时候i在增加,而node.ele_num在减少,会导致有的点没有插进去
    						 //所以直接在循环结束后,将node.ele_num置为0即可
    	}
        node->ele_num = 0;
    }
    
    //创建子节点
    QuadTreeNode *createChildNode(struct QuadTreeNode *node, double bottom, double up, double left, double right)
    {
    	int depth = node->depth + 1;
    	QuadTreeNode *childNode = (QuadTreeNode *) malloc(sizeof(QuadTreeNode));
    	Region *region = (Region *) malloc(sizeof(Region));
    	initRegion(region, bottom, up, left, right);
    	initNode(childNode, depth, *region);
    
    	return childNode;
    }
    
    
    //区域查询  输出该点所在的矩形区域的所有点
    void queryEle(struct QuadTreeNode node, struct ElePoint ele) 
    {
    	//是叶子结点
    	if (node.is_leaf == 1) 
    	{
    		cout << "附近点有" << node.ele_num << "个,分别是:" << endl;
    		for (int j = 0; j < node.ele_num; j++)
    		{
    			cout << "(" << node.ele_list[j]->lng << "," << node.ele_list[j]->lat << ")";
    		}
    		return;
    	}
    
    	//不是叶子节点
    	double mid_vertical = (node.region.up + node.region.bottom) / 2;
    	double mid_horizontal = (node.region.left + node.region.right) / 2;
    
    	if (ele.lat > mid_vertical) 
    	{
    		if (ele.lng > mid_horizontal) 
    		{
    			queryEle(*node.RU, ele);
    		}
    		else 
    		{
    			queryEle(*node.LU, ele);
    		}
    	}
    	else
    	{
    		if (ele.lng > mid_horizontal)
    		{
    			queryEle(*node.RB, ele);
    		}
    		else
    		{
    			queryEle(*node.LB, ele);
    		}
    	}
    }
    
    
    //点查询
    void queryPoint(QuadTreeNode node, ElePoint &ele)
    {
    	//是叶子节点
    	if (node.is_leaf == 1)
    	{
    		for (int i = 0; i < node.ele_num; i++)
    		{
    			if (ele.lng == node.ele_list[i].lng&&ele.lat == node.ele_list[i].lat)
    			{
    				cout << "(" << node.ele_list[i].lng << "," << node.ele_list[i].lat << ") 位于第" << node.depth << "层" << endl;
    				return;
    			}
    		}
    		cout << "未找到该点!" << endl;
    		return;
    	}
    
    	//不是叶子结点
    	double mid_vertical = (node.rect.up + node.rect.bottom) / 2;
    	double mid_horizontal = (node.rect.left + node.rect.right) / 2;
    
    	if (ele.lng > mid_horizontal) {
    		if (ele.lat > mid_vertical) {
    			queryPoint(QTList[node.RU_0], ele);
    		}
    		else {
    			queryPoint(QTList[node.RB_3], ele);
    		}
    	}
    	else {
    		if (ele.lat > mid_vertical) {
    			queryPoint(QTList[node.LU_1], ele);
    		}
    		else {
    			queryPoint(QTList[node.LB_2], ele);
    		}
    	}
    }
    
    
    //任意区域查询
    void queryArea(QuadTreeNode *node, Region *region)
    {	//是叶子节点
    	if (node->is_leaf == 1)
    	{	
    		//遍历叶子节点中的所有点
    		for (int i = 0; i < node->ele_num; i++) 
    		{	
    			//如果叶子节点中有点在该矩形区域中,就输出该点坐标
    			if (node->ele_list[i]->lng >= region->left &&
    				node->ele_list[i]->lng <= region->right &&
    				node->ele_list[i]->lat >= region->bottom &&
    				node->ele_list[i]->lat <= region->up) 
    			{
    				cout << "(" << node->ele_list[i]->lng << "," << node->ele_list[i]->lat << ") ";
    			}
    		}
    		cout << endl;
    		return;
    	}
    	
    	//不是叶子结点 , 递归查找与矩形区域有交集的叶子结点
    	double mid_vertical = (node->region.up + node->region.bottom) / 2;
    	double mid_horizontal = (node->region.left + node->region.right) / 2;
    
    	//讨论矩形区域的9种分布情况
    	if (region->bottom > mid_vertical){
    		if (region->left > mid_horizontal){
    			//如果矩形区域的下边界大,左边界大,就在右上区域查询
    			queryArea(node->RU, region);
    		}
    		else if (region->right < mid_horizontal){
    			queryArea(node->LU, region);
    		}
    		else{
    			//将该矩形区域分成两块,逐块递归判断其所属的子区域
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { region->bottom,region->up,region->left,mid_horizontal };
    			queryArea(node->LU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,region->up,mid_horizontal,region->right };
    			queryArea(node->RU, region2);
    		}
    	}
    
    	else if (region->up < mid_vertical){
    		if (region->right < mid_horizontal){
    			queryArea(node->LB, region);
    		}
    		else if (region->left > mid_horizontal){
    			queryArea(node->RB, region);
    		}
    		else{
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { region->bottom, region->up,region->left,mid_horizontal };
    			queryArea(node->LB, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,region->up,mid_horizontal,region->right };
    			queryArea(node->RB, region2);
    		}
    	}
    
    	else{
    		if (region->right < mid_horizontal){
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { mid_vertical,region->up,region->left,region->right };
    			queryArea(node->LU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,mid_vertical,region->left,region->right };
    			queryArea(node->LB, region2);
    
    		}
    		else if (region->left > mid_horizontal)	{
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { mid_vertical,region->up,region->left,region->right };
    			queryArea(node->RU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { region->bottom,mid_vertical,region->left,region->right };
    			queryArea(node->RB, region2);
    		}
    		else {
    			Region *region1 = (Region *)malloc(sizeof(Region));
    			*region1 = { mid_vertical,region->up,region->left,mid_horizontal };
    			queryArea(node->LU, region1);
    
    			Region *region2 = (Region *)malloc(sizeof(Region));
    			*region2 = { mid_vertical,region->up,mid_horizontal,region->right };
    			queryArea(node->RU, region2);
    
    			Region *region3 = (Region *)malloc(sizeof(Region));
    			*region3 = { region->bottom,mid_vertical,region->left,mid_horizontal };
    			queryArea(node->LB, region3);
    
    			Region *region4 = (Region *)malloc(sizeof(Region));
    			*region4 = { region->bottom, mid_vertical,mid_horizontal,region->right };
    			queryArea(node->RB, region4);
    		}
    	}
    }
    
    
    //初始化四叉树结点
    void initNode(QuadTreeNode *node, int depth, Region region)
    {
    	node->depth = depth;
    	node->is_leaf = 1;
    	node->ele_num = 0;
    	node->region = region;
    }
     
    //初始化矩形区域
    void initRegion(Region *region, double bottom, double up, double left, double right) 
    {
    	region->bottom = bottom;
    	region->up = up;
    	region->left = left;
    	region->right = right;
    }
    
    
    //测试
    int main()
    {
    	QuadTreeNode root;
    	Region root_region;
    
    	ElePoint ele;
    	initRegion(&root_region, -90, 90, -180, 180);
    	initNode(&root, 1, root_region);
    
    	srand((unsigned)time(NULL));  //随机数种子
    	for (int i = 0; i < 100000; i++) 
    	{
    		ele.lng = (float)(rand() % 360 - 180 + (float)(rand() % 1000) / 1000);
    		ele.lat = (float)(rand() % 180 - 90 + (float)(rand() % 1000) / 10000);
    		insertEle(&root, ele);
    	}
    
    	ElePoint test;
    	test.lat = -24;
    	test.lng = -45.4;
    	queryEle(root, test);
    
        ElePoint point1;
    	point1.lng = 54.1;
    	point1.lat = 12.1;
    	insertEle(&root, point1);
    
    	ElePoint point2;
    	point2.lng = -12.1;
    	point2.lat = -42.5;
    	insertEle(&root, point2);
    
    	ElePoint point3;
    	point3.lng = 50.2;
    	point3.lat = 12.3;
    
    	Query_point(&root, point1);
    	Query_point(&root, point2);
    	Query_point(&root, point3);
    
    	Region region2;
    	initRegion(&region2, -20, 20, -20, 20);
    
    	ElePoint point4;
    	point4.lng = 2.12;
    	point4.lat = 2.34;
    	insertEle(&root, point4);
    
    	cout << "任意区域查询" << endl;
    	queryArea(&root, &region2);
        
    	system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
  • 相关阅读:
    Arduino红外循迹小车代码笔记和常见问题解决
    python(43) dbf文件读写
    Linux防火墙实现SNAT与DNAT
    类与对象(十四)----包package
    Redis 介绍&安装
    【mysql】innodb_locks不能存在
    选好冒烟测试用例,为进入QA的制品包把好第一道关
    《向量数据库指南》——TruLens 用于语言模型应用跟踪和评估
    4、Linux:如何在zip压缩文件中搜索指定内容
    STC15W单片机防丢语音报警GPS北斗定位测距双机LORA无线手持可充电
  • 原文地址:https://blog.csdn.net/qq_44372971/article/details/126266383