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

 

java 四叉树 算法实现 四叉树结构算法_子节点

四叉树示意图

 

四叉树对于区域查询,效率比较高。但如果空间对象分布不均匀,随着地理空间对象的不断插入,四叉树的层次会不断地加深,将形成一棵严重不平衡的四叉树,那么每次查询的深度将大大的增多,从而导致查询效率的急剧下降。

 

本节将介绍一种改进的四叉树索引结构。四叉树结构是自顶向下逐步划分的一种树状的层次结构。传统的四叉树索引存在着以下几个缺点:

(1)空间实体只能存储在叶子节点中,中间节点以及根节点不能存储空间实体信息,随着空间对象的不断插入,最终会导致四叉树树的层次比较深,在进行空间数据窗口查询的时候效率会比较低下。

(2)同一个地理实体在四叉树的分裂过程中极有可能存储在多个节点中,这样就导致了索引存储空间的浪费。

(3)由于地理空间对象可能分布不均衡,这样会导致常规四叉树生成一棵极为不平衡的树,这样也会造成树结构的不平衡以及存储空间的浪费。

相应的改进方法,将地理实体信息存储在完全包含它的最小矩形节点中,不存储在它的父节点中,每个地理实体只在树中存储一次,避免存储空间的浪费。首先生成满四叉树,避免在地理实体插入时需要重新分配内存,加快插入的速度,最后将空的节点所占内存空间释放掉。改进后的四叉树结构如下图所示。四叉树的深度一般取经验值4-7之间为最佳。

 

java 四叉树 算法实现 四叉树结构算法_四叉树_02

图改进的四叉树结构

 

为了维护空间索引与对存储在文件或数据库中的空间数据的一致性,作者设计了如下的数据结构支持四叉树的操作。

(1)四分区域标识

分别定义了一个平面区域的四个子区域索引号,右上为第一象限0,左上为第二象限1,左下为第三象限2,右下为第四象限3。

typedef enum

{

      UR = 0,// UR第一象限

      UL = 1, // UL为第二象限

      LL = 2, // LL为第三象限

      LR = 3  // LR为第四象限

}QuadrantEnum;

(2)空间对象数据结构

空间对象数据结构是对地理空间对象的近似,在空间索引中,相当一部分都是采用MBR作为近似。

/*空间对象MBR信息*/

typedef struct SHPMBRInfo

{

      int nID;       //空间对象ID号

      MapRect Box;    //空间对象MBR范围坐标

}SHPMBRInfo;

nID是空间对象的标识号,Box是空间对象的最小外包矩形(MBR)。

(3)四叉树节点数据结构

四叉树节点是四叉树结构的主要组成部分,主要用于存储空间对象的标识号和MBR,也是四叉树算法操作的主要部分。

/*四叉树节点类型结构*/

typedef struct QuadNode
{
      MapRect            Box;                   //节点所代表的矩形区域
      int                nShpCount;        //节点所包含的所有空间对象个数
      SHPMBRInfo* pShapeObj;          //空间对象指针数组
      int         nChildCount;            //子节点个数
      QuadNode *children[4];             //指向节点的四个孩子
}QuadNode;

Box是代表四叉树对应区域的最小外包矩形,上一层的节点的最小外包矩形包含下一层最小外包矩形区域;nShpCount代表本节点包含的空间对象的个数;pShapeObj代表指向空间对象存储地址的首地址,同一个节点的空间对象在内存中连续存储;nChildCount代表节点拥有的子节点的数目;children是指向孩子节点指针的数组。

上述理论部分都都讲的差不多了,下面就贴上我的C语言实现版本代码。

头文件如下:


[cpp] view plain copy



    1. #ifndef __QUADTREE_H_59CAE94A_E937_42AD_AA27_794E467715BB__  
    2. #define __QUADTREE_H_59CAE94A_E937_42AD_AA27_794E467715BB__  
    3.   
    4.   
    5.   
    6.   
    7. /* 一个矩形区域的象限划分:: 
    8.  
    9. UL(1)   |    UR(0) 
    10. ----------|----------- 
    11. LL(2)   |    LR(3) 
    12. 以下对该象限类型的枚举 
    13. */  
    14. typedef enum  
    15. {  
    16.     UR = 0,  
    17.     UL = 1,  
    18.     LL = 2,  
    19.     LR = 3  
    20. }QuadrantEnum;  
    21.   
    22. /*空间对象MBR信息*/  
    23. typedef struct SHPMBRInfo  
    24. {  
    25.     int nID;        //空间对象ID号  
    26.     MapRect Box;    //空间对象MBR范围坐标  
    27. }SHPMBRInfo;  
    28.   
    29. /* 四叉树节点类型结构 */  
    30. typedef struct QuadNode  
    31. {  
    32.     MapRect     Box;            //节点所代表的矩形区域  
    33.     int         nShpCount;      //节点所包含的所有空间对象个数  
    34.     SHPMBRInfo* pShapeObj;      //空间对象指针数组  
    35.     int     nChildCount;        //子节点个数  
    36.     QuadNode  *children[4];     //指向节点的四个孩子   
    37. }QuadNode;  
    38.   
    39. /* 四叉树类型结构 */  
    40. typedef struct quadtree_t  
    41. {  
    42.     QuadNode  *root;  
    43.     int         depth;           // 四叉树的深度                      
    44. }QuadTree;  
    45.   
    46.   
    47.     //初始化四叉树节点  
    48.     QuadNode *InitQuadNode();  
    49.   
    50.     //层次创建四叉树方法(满四叉树)  
    51.     void CreateQuadTree(int depth,GeoLayer *poLayer,QuadTree* pQuadTree);  
    52.   
    53.     //创建各个分支  
    54.     void CreateQuadBranch(int depth,MapRect &rect,QuadNode** node);  
    55.   
    56.     //构建四叉树空间索引  
    57.     void BuildQuadTree(GeoLayer*poLayer,QuadTree* pQuadTree);  
    58.   
    59.     //四叉树索引查询(矩形查询)  
    60.     void SearchQuadTree(QuadNode* node,MapRect &queryRect,vector<int>& ItemSearched);  
    61.   
    62.     //四叉树索引查询(矩形查询)并行查询  
    63.     void SearchQuadTreePara(vector<QuadNode*> resNodes,MapRect &queryRect,vector<int>& ItemSearched);  
    64.   
    65.     //四叉树的查询(点查询)  
    66.     void PtSearchQTree(QuadNode* node,double cx,double cy,vector<int>& ItemSearched);  
    67.   
    68.     //将指定的空间对象插入到四叉树中  
    69.     void Insert(long key,MapRect &itemRect,QuadNode* pNode);  
    70.   
    71.     //将指定的空间对象插入到四叉树中  
    72.     void InsertQuad(long key,MapRect &itemRect,QuadNode* pNode);  
    73.   
    74.     //将指定的空间对象插入到四叉树中  
    75.     void InsertQuad2(long key,MapRect &itemRect,QuadNode* pNode);  
    76.   
    77.     //判断一个节点是否是叶子节点  
    78.     bool IsQuadLeaf(QuadNode* node);  
    79.   
    80.     //删除多余的节点  
    81.     bool DelFalseNode(QuadNode* node);  
    82.   
    83.     //四叉树遍历(所有要素)  
    84.     void TraversalQuadTree(QuadNode* quadTree,vector<int>& resVec);  
    85.   
    86.     //四叉树遍历(所有节点)  
    87.     void TraversalQuadTree(QuadNode* quadTree,vector<QuadNode*>& arrNode);  
    88.   
    89.     //释放树的内存空间  
    90.     void ReleaseQuadTree(QuadNode** quadTree);  
    91.   
    92.     //计算四叉树所占的字节的大小  
    93.     long CalByteQuadTree(QuadNode* quadTree,long& nSize);  
    94.   
    95.   
    96. #endif


    源文件如下:


    [cpp] view plain copy



      1. #include "QuadTree.h"  
      2.   
      3.   
      4. QuadNode *InitQuadNode()  
      5. {  
      6.     QuadNode *node = new QuadNode;  
      7.     node->Box.maxX = 0;  
      8.     node->Box.maxY = 0;  
      9.     node->Box.minX = 0;  
      10.     node->Box.minY = 0;  
      11.   
      12.     for (int i = 0; i < 4; i ++)  
      13.     {  
      14.         node->children[i] = NULL;  
      15.     }  
      16.     node->nChildCount = 0;  
      17.     node->nShpCount = 0;  
      18.     node->pShapeObj = NULL;  
      19.   
      20.     return node;  
      21. }  
      22.   
      23. void CreateQuadTree(int depth,GeoLayer *poLayer,QuadTree* pQuadTree)  
      24. {  
      25.     pQuadTree->depth = depth;  
      26.   
      27.     GeoEnvelope env;    //整个图层的MBR  
      28.     poLayer->GetExtent(&env);  
      29.       
      30.     MapRect rect;  
      31.     rect.minX = env.MinX;  
      32.     rect.minY = env.MinY;  
      33.     rect.maxX = env.MaxX;  
      34.     rect.maxY = env.MaxY;  
      35.       
      36.     //创建各个分支  
      37.     CreateQuadBranch(depth,rect,&(pQuadTree->root));  
      38.   
      39.     int nCount = poLayer->GetFeatureCount();  
      40.     GeoFeature **pFeatureClass = new GeoFeature*[nCount];  
      41.     for (int i = 0; i < poLayer->GetFeatureCount(); i ++)  
      42.     {  
      43.         pFeatureClass[i] = poLayer->GetFeature(i);   
      44.     }  
      45.   
      46.     //插入各个要素  
      47.     GeoEnvelope envObj; //空间对象的MBR  
      48.     //#pragma omp parallel for  
      49.     for (int i = 0; i < nCount; i ++)  
      50.     {  
      51.         pFeatureClass[i]->GetGeometry()->getEnvelope(&envObj);  
      52.         rect.minX = envObj.MinX;  
      53.         rect.minY = envObj.MinY;  
      54.         rect.maxX = envObj.MaxX;  
      55.         rect.maxY = envObj.MaxY;  
      56.         InsertQuad(i,rect,pQuadTree->root);  
      57.     }  
      58.   
      59.     //DelFalseNode(pQuadTree->root);  
      60. }  
      61.   
      62. void CreateQuadBranch(int depth,MapRect &rect,QuadNode** node)  
      63. {  
      64.     if (depth != 0)  
      65.     {  
      66.         *node = InitQuadNode(); //创建树根  
      67.         QuadNode *pNode = *node;  
      68.         pNode->Box = rect;  
      69.         pNode->nChildCount = 4;  
      70.   
      71.         MapRect boxs[4];  
      72.         pNode->Box.Split(boxs,boxs+1,boxs+2,boxs+3);  
      73.         for (int i = 0; i < 4; i ++)  
      74.         {  
      75.             //创建四个节点并插入相应的MBR  
      76.             pNode->children[i] = InitQuadNode();  
      77.             pNode->children[i]->Box = boxs[i];  
      78.   
      79.             CreateQuadBranch(depth-1,boxs[i],&(pNode->children[i]));  
      80.         }  
      81.     }  
      82. }  
      83.   
      84. void BuildQuadTree(GeoLayer *poLayer,QuadTree* pQuadTree)  
      85. {  
      86.     assert(poLayer);  
      87.     GeoEnvelope env;    //整个图层的MBR  
      88.     poLayer->GetExtent(&env);  
      89.     pQuadTree->root = InitQuadNode();  
      90.   
      91.     QuadNode* rootNode = pQuadTree->root;  
      92.   
      93.     rootNode->Box.minX = env.MinX;  
      94.     rootNode->Box.minY = env.MinY;  
      95.     rootNode->Box.maxX = env.MaxX;  
      96.     rootNode->Box.maxY = env.MaxY;  
      97.   
      98.     //设置树的深度(   根据等比数列的求和公式)  
      99.     //pQuadTree->depth = log(poLayer->GetFeatureCount()*3/8.0+1)/log(4.0);  
      100.     int nCount = poLayer->GetFeatureCount();  
      101.   
      102.     MapRect rect;  
      103.     GeoEnvelope envObj; //空间对象的MBR  
      104.     for (int i = 0; i < nCount; i ++)  
      105.     {  
      106.         poLayer->GetFeature(i)->GetGeometry()->getEnvelope(&envObj);  
      107.         rect.minX = envObj.MinX;  
      108.         rect.minY = envObj.MinY;  
      109.         rect.maxX = envObj.MaxX;  
      110.         rect.maxY = envObj.MaxY;  
      111.         InsertQuad2(i,rect,rootNode);  
      112.     }  
      113.   
      114.     DelFalseNode(pQuadTree->root);  
      115. }  
      116.   
      117. void SearchQuadTree(QuadNode* node,MapRect &queryRect,vector<int>& ItemSearched)  
      118. {  
      119.     assert(node);  
      120.   
      121.     //int coreNum = omp_get_num_procs();  
      122.     //vector<int> * pResArr = new vector<int>[coreNum];  
      123.   
      124.     if (NULL != node)  
      125.     {  
      126.         for (int i = 0; i < node->nShpCount; i ++)  
      127.         {  
      128.             if (queryRect.Contains(node->pShapeObj[i].Box)  
      129.                 || queryRect.Intersects(node->pShapeObj[i].Box))  
      130.             {  
      131.                 ItemSearched.push_back(node->pShapeObj[i].nID);  
      132.             }  
      133.         }  
      134.   
      135.         //并行搜索四个孩子节点  
      136.         /*#pragma omp parallel sections 
      137.         { 
      138.             #pragma omp section 
      139.             if ((node->children[0] != NULL) &&  
      140.                 (node->children[0]->Box.Contains(queryRect) 
      141.                 || node->children[0]->Box.Intersects(queryRect))) 
      142.             { 
      143.                 int tid = omp_get_thread_num(); 
      144.                 SearchQuadTree(node->children[0],queryRect,pResArr[tid]); 
      145.             } 
      146.  
      147.             #pragma omp section 
      148.             if ((node->children[1] != NULL) &&  
      149.                 (node->children[1]->Box.Contains(queryRect) 
      150.                 || node->children[1]->Box.Intersects(queryRect))) 
      151.             { 
      152.                 int tid = omp_get_thread_num(); 
      153.                 SearchQuadTree(node->children[1],queryRect,pResArr[tid]); 
      154.             } 
      155.  
      156.             #pragma omp section 
      157.             if ((node->children[2] != NULL) &&  
      158.                 (node->children[2]->Box.Contains(queryRect) 
      159.                 || node->children[2]->Box.Intersects(queryRect))) 
      160.             { 
      161.                 int tid = omp_get_thread_num(); 
      162.                 SearchQuadTree(node->children[2],queryRect,pResArr[tid]); 
      163.             } 
      164.  
      165.             #pragma omp section 
      166.             if ((node->children[3] != NULL) &&  
      167.                 (node->children[3]->Box.Contains(queryRect) 
      168.                 || node->children[3]->Box.Intersects(queryRect))) 
      169.             { 
      170.                 int tid = omp_get_thread_num(); 
      171.                 SearchQuadTree(node->children[3],queryRect,pResArr[tid]); 
      172.             } 
      173.         }*/  
      174.         for (int i = 0; i < 4; i ++)  
      175.         {  
      176.             if ((node->children[i] != NULL) &&   
      177.                 (node->children[i]->Box.Contains(queryRect)  
      178.                 || node->children[i]->Box.Intersects(queryRect)))  
      179.             {  
      180.                 SearchQuadTree(node->children[i],queryRect,ItemSearched);  
      181.                 //node = node->children[i];  //非递归  
      182.             }  
      183.         }  
      184.     }  
      185.   
      186.     /*for (int i = 0 ; i < coreNum; i ++) 
      187.     { 
      188.         ItemSearched.insert(ItemSearched.end(),pResArr[i].begin(),pResArr[i].end()); 
      189.     }*/  
      190.   
      191. }  
      192.   
      193. void SearchQuadTreePara(vector<QuadNode*> resNodes,MapRect &queryRect,vector<int>& ItemSearched)  
      194. {  
      195.     int coreNum = omp_get_num_procs();  
      196.     omp_set_num_threads(coreNum);  
      197.     vector<int>* searchArrs = new vector<int>[coreNum];  
      198.     for (int i = 0; i < coreNum; i ++)  
      199.     {  
      200.         searchArrs[i].clear();  
      201.     }  
      202.   
      203.     #pragma omp parallel for  
      204.     for (int i = 0; i < resNodes.size(); i ++)  
      205.     {  
      206.         int tid = omp_get_thread_num();  
      207.         for (int j = 0; j < resNodes[i]->nShpCount; j ++)  
      208.         {  
      209.             if (queryRect.Contains(resNodes[i]->pShapeObj[j].Box)  
      210.                 || queryRect.Intersects(resNodes[i]->pShapeObj[j].Box))  
      211.             {  
      212.                 searchArrs[tid].push_back(resNodes[i]->pShapeObj[j].nID);  
      213.             }  
      214.         }  
      215.     }  
      216.   
      217.     for (int i = 0; i < coreNum; i ++)  
      218.     {  
      219.         ItemSearched.insert(ItemSearched.end(),  
      220.             searchArrs[i].begin(),searchArrs[i].end());  
      221.     }  
      222.   
      223.     delete [] searchArrs;  
      224.     searchArrs = NULL;  
      225. }  
      226.   
      227. void PtSearchQTree(QuadNode* node,double cx,double cy,vector<int>& ItemSearched)  
      228. {  
      229.     assert(node);  
      230.     if (node->nShpCount >0)       //节点            
      231.     {  
      232.         for (int i = 0; i < node->nShpCount; i ++)  
      233.         {  
      234.             if (node->pShapeObj[i].Box.IsPointInRect(cx,cy))  
      235.             {  
      236.                 ItemSearched.push_back(node->pShapeObj[i].nID);  
      237.             }  
      238.         }  
      239.     }  
      240.   
      241.     else if (node->nChildCount >0)                //节点  
      242.     {  
      243.         for (int i = 0; i < 4; i ++)  
      244.         {  
      245.             if (node->children[i]->Box.IsPointInRect(cx,cy))  
      246.             {  
      247.                 PtSearchQTree(node->children[i],cx,cy,ItemSearched);  
      248.             }  
      249.         }  
      250.     }  
      251.   
      252.     //找出重复元素的位置  
      253.     sort(ItemSearched.begin(),ItemSearched.end());  //先排序,默认升序  
      254.     vector<int>::iterator unique_iter =   
      255.         unique(ItemSearched.begin(),ItemSearched.end());  
      256.     ItemSearched.erase(unique_iter,ItemSearched.end());  
      257. }  
      258.   
      259. void Insert(long key, MapRect &itemRect,QuadNode* pNode)  
      260. {  
      261.     QuadNode *node = pNode;     //保留根节点副本  
      262.     SHPMBRInfo pShpInfo;  
      263.       
      264.     //节点有孩子  
      265.     if (0 < node->nChildCount)  
      266.     {  
      267.         for (int i = 0; i < 4; i ++)  
      268.         {    
      269.             //如果包含或相交,则将节点插入到此节点  
      270.             if (node->children[i]->Box.Contains(itemRect)  
      271.                 || node->children[i]->Box.Intersects(itemRect))  
      272.             {  
      273.                 //node = node->children[i];  
      274.                 Insert(key,itemRect,node->children[i]);  
      275.             }  
      276.         }  
      277.     }  
      278.   
      279.     //如果当前节点存在一个子节点时  
      280.     else if (1 == node->nShpCount)  
      281.     {  
      282.         MapRect boxs[4];  
      283.         node->Box.Split(boxs,boxs+1,boxs+2,boxs+3);  
      284.   
      285.         //创建四个节点并插入相应的MBR  
      286.         node->children[UR] = InitQuadNode();  
      287.         node->children[UL] = InitQuadNode();  
      288.         node->children[LL] = InitQuadNode();  
      289.         node->children[LR] = InitQuadNode();  
      290.   
      291.         node->children[UR]->Box = boxs[0];  
      292.         node->children[UL]->Box = boxs[1];  
      293.         node->children[LL]->Box = boxs[2];  
      294.         node->children[LR]->Box = boxs[3];  
      295.         node->nChildCount = 4;  
      296.   
      297.         for (int i = 0; i < 4; i ++)  
      298.         {    
      299.             //将当前节点中的要素移动到相应的子节点中  
      300.             for (int j = 0; j < node->nShpCount; j ++)  
      301.             {  
      302.                 if (node->children[i]->Box.Contains(node->pShapeObj[j].Box)  
      303.                     || node->children[i]->Box.Intersects(node->pShapeObj[j].Box))  
      304.                 {  
      305.                     node->children[i]->nShpCount += 1;  
      306.                     node->children[i]->pShapeObj =   
      307.                         (SHPMBRInfo*)malloc(node->children[i]->nShpCount*sizeof(SHPMBRInfo));  
      308.                       
      309.                     memcpy(node->children[i]->pShapeObj,&(node->pShapeObj[j]),sizeof(SHPMBRInfo));  
      310.   
      311.                     free(node->pShapeObj);  
      312.                     node->pShapeObj = NULL;  
      313.                     node->nShpCount = 0;  
      314.                 }  
      315.             }  
      316.         }  
      317.   
      318.         for (int i = 0; i < 4; i ++)  
      319.         {    
      320.             //如果包含或相交,则将节点插入到此节点  
      321.             if (node->children[i]->Box.Contains(itemRect)  
      322.                 || node->children[i]->Box.Intersects(itemRect))  
      323.             {  
      324.                 if (node->children[i]->nShpCount == 0)     //如果之前没有节点  
      325.                 {  
      326.                     node->children[i]->nShpCount += 1;  
      327.                     node->pShapeObj =   
      328.                         (SHPMBRInfo*)malloc(sizeof(SHPMBRInfo)*node->children[i]->nShpCount);  
      329.                 }  
      330.                 else if (node->children[i]->nShpCount > 0)  
      331.                 {  
      332.                     node->children[i]->nShpCount += 1;  
      333.                     node->children[i]->pShapeObj =   
      334.                         (SHPMBRInfo *)realloc(node->children[i]->pShapeObj,  
      335.                         sizeof(SHPMBRInfo)*node->children[i]->nShpCount);  
      336.                 }  
      337.   
      338.                 pShpInfo.Box = itemRect;  
      339.                 pShpInfo.nID = key;  
      340.                 memcpy(node->children[i]->pShapeObj,  
      341.                     &pShpInfo,sizeof(SHPMBRInfo));  
      342.             }  
      343.         }  
      344.     }  
      345.   
      346.     //当前节点没有空间对象  
      347.     else if (0 == node->nShpCount)  
      348.     {  
      349.         node->nShpCount += 1;  
      350.         node->pShapeObj =   
      351.             (SHPMBRInfo*)malloc(sizeof(SHPMBRInfo)*node->nShpCount);  
      352.   
      353.         pShpInfo.Box = itemRect;  
      354.         pShpInfo.nID = key;  
      355.         memcpy(node->pShapeObj,&pShpInfo,sizeof(SHPMBRInfo));  
      356.     }  
      357. }  
      358.   
      359. void InsertQuad(long key,MapRect &itemRect,QuadNode* pNode)  
      360. {  
      361.     assert(pNode != NULL);  
      362.   
      363.     if (!IsQuadLeaf(pNode))    //非叶子节点  
      364.     {  
      365.         int nCorver = 0;        //跨越的子节点个数  
      366.         int iIndex = -1;        //被哪个子节点完全包含的索引号  
      367.         for (int i = 0; i < 4; i ++)  
      368.         {  
      369.             if (pNode->children[i]->Box.Contains(itemRect)  
      370.                 && pNode->Box.Contains(itemRect))  
      371.             {  
      372.                 nCorver += 1;  
      373.                 iIndex = i;  
      374.             }  
      375.         }  
      376.   
      377.         //如果被某一个子节点包含,则进入该子节点  
      378.         if (/*pNode->Box.Contains(itemRect) ||  
      379.             pNode->Box.Intersects(itemRect)*/1 <= nCorver)  
      380.         {   
      381.             InsertQuad(key,itemRect,pNode->children[iIndex]);  
      382.         }  
      383.   
      384.         //如果跨越了多个子节点,直接放在这个节点中  
      385.         else if (nCorver == 0)  
      386.         {  
      387.             if (pNode->nShpCount == 0)    //如果之前没有节点  
      388.             {  
      389.                 pNode->nShpCount += 1;  
      390.                 pNode->pShapeObj =   
      391.                     (SHPMBRInfo*)malloc(sizeof(SHPMBRInfo)*pNode->nShpCount);  
      392.             }  
      393.             else  
      394.             {  
      395.                 pNode->nShpCount += 1;  
      396.                 pNode->pShapeObj =   
      397.                     (SHPMBRInfo *)realloc(pNode->pShapeObj,sizeof(SHPMBRInfo)*pNode->nShpCount);  
      398.             }  
      399.   
      400.             SHPMBRInfo pShpInfo;  
      401.             pShpInfo.Box = itemRect;  
      402.             pShpInfo.nID = key;  
      403.             memcpy(pNode->pShapeObj+pNode->nShpCount-1,&pShpInfo,sizeof(SHPMBRInfo));  
      404.         }  
      405.     }  
      406.   
      407.     //如果是叶子节点,直接放进去  
      408.     else if (IsQuadLeaf(pNode))  
      409.     {  
      410.         if (pNode->nShpCount == 0)    //如果之前没有节点  
      411.         {  
      412.             pNode->nShpCount += 1;  
      413.             pNode->pShapeObj =   
      414.                 (SHPMBRInfo*)malloc(sizeof(SHPMBRInfo)*pNode->nShpCount);  
      415.         }  
      416.         else  
      417.         {  
      418.             pNode->nShpCount += 1;  
      419.             pNode->pShapeObj =   
      420.                 (SHPMBRInfo *)realloc(pNode->pShapeObj,sizeof(SHPMBRInfo)*pNode->nShpCount);  
      421.         }  
      422.   
      423.         SHPMBRInfo pShpInfo;  
      424.         pShpInfo.Box = itemRect;  
      425.         pShpInfo.nID = key;  
      426.         memcpy(pNode->pShapeObj+pNode->nShpCount-1,&pShpInfo,sizeof(SHPMBRInfo));  
      427.     }  
      428. }  
      429.   
      430. void InsertQuad2(long key,MapRect &itemRect,QuadNode* pNode)  
      431. {  
      432.     QuadNode *node = pNode;     //保留根节点副本  
      433.     SHPMBRInfo pShpInfo;  
      434.   
      435.     //节点有孩子  
      436.     if (0 < node->nChildCount)  
      437.     {  
      438.         for (int i = 0; i < 4; i ++)  
      439.         {    
      440.             //如果包含或相交,则将节点插入到此节点  
      441.             if (node->children[i]->Box.Contains(itemRect)  
      442.                 || node->children[i]->Box.Intersects(itemRect))  
      443.             {  
      444.                 //node = node->children[i];  
      445.                 Insert(key,itemRect,node->children[i]);  
      446.             }  
      447.         }  
      448.     }  
      449.   
      450.     //如果当前节点存在一个子节点时  
      451.     else if (0 == node->nChildCount)  
      452.     {  
      453.         MapRect boxs[4];  
      454.         node->Box.Split(boxs,boxs+1,boxs+2,boxs+3);  
      455.   
      456.         int cnt = -1;  
      457.         for (int i = 0; i < 4; i ++)  
      458.         {    
      459.             //如果包含或相交,则将节点插入到此节点  
      460.             if (boxs[i].Contains(itemRect))  
      461.             {  
      462.                 cnt = i;  
      463.             }  
      464.         }  
      465.   
      466.         //如果有一个矩形包含此对象,则创建四个孩子节点  
      467.         if (cnt > -1)  
      468.         {  
      469.             for (int i = 0; i < 4; i ++)  
      470.             {  
      471.                 //创建四个节点并插入相应的MBR  
      472.                 node->children[i] = InitQuadNode();  
      473.                 node->children[i]->Box = boxs[i];  
      474.             }  
      475.             node->nChildCount = 4;  
      476.             InsertQuad2(key,itemRect,node->children[cnt]);   //递归  
      477.         }  
      478.   
      479.         //如果都不包含,则直接将对象插入此节点  
      480.         if (cnt == -1)  
      481.         {  
      482.             if (node->nShpCount == 0)     //如果之前没有节点  
      483.             {  
      484.                 node->nShpCount += 1;  
      485.                 node->pShapeObj =   
      486.                     (SHPMBRInfo*)malloc(sizeof(SHPMBRInfo)*node->nShpCount);  
      487.             }  
      488.             else if (node->nShpCount > 0)  
      489.             {  
      490.                 node->nShpCount += 1;  
      491.                 node->pShapeObj =   
      492.                     (SHPMBRInfo *)realloc(node->pShapeObj,  
      493.                     sizeof(SHPMBRInfo)*node->nShpCount);  
      494.             }  
      495.   
      496.             pShpInfo.Box = itemRect;  
      497.             pShpInfo.nID = key;  
      498.             memcpy(node->pShapeObj,  
      499.                 &pShpInfo,sizeof(SHPMBRInfo));  
      500.         }  
      501.     }  
      502.   
      503.     //当前节点没有空间对象  
      504.     /*else if (0 == node->nShpCount) 
      505.     { 
      506.         node->nShpCount += 1; 
      507.         node->pShapeObj =  
      508.             (SHPMBRInfo*)malloc(sizeof(SHPMBRInfo)*node->nShpCount); 
      509.  
      510.         pShpInfo.Box = itemRect; 
      511.         pShpInfo.nID = key; 
      512.         memcpy(node->pShapeObj,&pShpInfo,sizeof(SHPMBRInfo)); 
      513.     }*/  
      514. }  
      515.   
      516. bool IsQuadLeaf(QuadNode* node)  
      517. {  
      518.     if (NULL == node)  
      519.     {  
      520.         return 1;  
      521.     }  
      522.     for (int i = 0; i < 4; i ++)  
      523.     {  
      524.         if (node->children[i] != NULL)  
      525.         {  
      526.             return 0;  
      527.         }  
      528.     }  
      529.   
      530.     return 1;  
      531. }  
      532.   
      533. bool DelFalseNode(QuadNode* node)  
      534. {  
      535.     //如果没有子节点且没有要素  
      536.     if (node->nChildCount ==0 && node->nShpCount == 0)  
      537.     {  
      538.         ReleaseQuadTree(&node);  
      539.     }  
      540.   
      541.     //如果有子节点  
      542.     else if (node->nChildCount > 0)  
      543.     {  
      544.         for (int i = 0; i < 4; i ++)  
      545.         {  
      546.             DelFalseNode(node->children[i]);  
      547.         }  
      548.     }  
      549.   
      550.     return 1;  
      551. }  
      552.   
      553. void TraversalQuadTree(QuadNode* quadTree,vector<int>& resVec)  
      554. {  
      555.     QuadNode *node = quadTree;  
      556.     int i = 0;   
      557.     if (NULL != node)  
      558.     {  
      559.         //将本节点中的空间对象存储数组中  
      560.         for (i = 0; i < node->nShpCount; i ++)  
      561.         {  
      562.             resVec.push_back((node->pShapeObj+i)->nID);  
      563.         }  
      564.   
      565.         //遍历孩子节点  
      566.         for (i = 0; i < node->nChildCount; i ++)  
      567.         {  
      568.             if (node->children[i] != NULL)  
      569.             {  
      570.                 TraversalQuadTree(node->children[i],resVec);  
      571.             }  
      572.         }  
      573.     }  
      574.   
      575. }  
      576.   
      577. void TraversalQuadTree(QuadNode* quadTree,vector<QuadNode*>& arrNode)  
      578. {  
      579.     deque<QuadNode*> nodeQueue;  
      580.     if (quadTree != NULL)  
      581.     {  
      582.         nodeQueue.push_back(quadTree);  
      583.         while (!nodeQueue.empty())  
      584.         {  
      585.             QuadNode* queueHead = nodeQueue.at(0);  //取队列头结点  
      586.             arrNode.push_back(queueHead);  
      587.             nodeQueue.pop_front();  
      588.             for (int i = 0; i < 4; i ++)  
      589.             {  
      590.                 if (queueHead->children[i] != NULL)  
      591.                 {  
      592.                     nodeQueue.push_back(queueHead->children[i]);  
      593.                 }  
      594.             }  
      595.         }  
      596.     }  
      597. }  
      598.   
      599. void ReleaseQuadTree(QuadNode** quadTree)  
      600. {  
      601.     int i = 0;  
      602.     QuadNode* node = *quadTree;  
      603.     if (NULL == node)  
      604.     {  
      605.         return;  
      606.     }  
      607.   
      608.     else  
      609.     {  
      610.         for (i = 0; i < 4; i ++)  
      611.         {   
      612.             ReleaseQuadTree(&node->children[i]);  
      613.         }  
      614.         free(node);  
      615.         node = NULL;  
      616.     }  
      617.   
      618.     node = NULL;  
      619. }  
      620.   
      621. long CalByteQuadTree(QuadNode* quadTree,long& nSize)  
      622. {  
      623.     if (quadTree != NULL)  
      624.     {  
      625.         nSize += sizeof(QuadNode)+quadTree->nChildCount*sizeof(SHPMBRInfo);  
      626.         for (int i = 0; i < 4; i ++)  
      627.         {  
      628.             if (quadTree->children[i] != NULL)  
      629.             {  
      630.                 nSize += CalByteQuadTree(quadTree->children[i],nSize);  
      631.             }  
      632.         }  
      633.     }  
      634.   
      635.     return 1;  
      636. }

      四叉树递归遍历叶节点并输出至数组

      原文链接:


      #include <stdlib.h>
      #include <string.h>
      #include <stdio.h>
      
      #define  CHILD_NUM    4
      typedef int Datatype;                // 节点数据类型
      typedef struct QuadTree* ChildType;  // 指向孩子节点指针
      
      int max_leaf_num = 1;                // 最大叶节点个数
      static int N = 0;                    // 对叶节点计数的全局变量
      
      // 四叉树节点结构
      struct QuadTree
      {
      	Datatype   data;     // 数据
      	ChildType  child[CHILD_NUM]; // 存放指向四个子树的指针数组
      };
      
      // 判断是否为叶节点,是返回1,不是返回0
      int isLeaf( QuadTree* node )  
      {
      	int i;
      	for ( i = 0; i < CHILD_NUM; ++i )
      	{
      		if ( node->child[i] != NULL ) // 如果存在子树,则不是叶节点
      			return 0;
      	}
      
      	return 1;
      }
      
      // 将长度为n的数组空间扩大两倍
      void expandArr( Datatype** out )
      {
      	int n = max_leaf_num;
      	Datatype* tmpArr = (Datatype*)malloc( sizeof(Datatype) * n);
      	memcpy( tmpArr, *out, sizeof(Datatype) * n);
      	free(*out);
      
      	*out = (Datatype*)malloc( sizeof(Datatype) * n * 2);
      	memcpy( *out, tmpArr, sizeof(Datatype) * n );
      	free( tmpArr );
      	max_leaf_num = n * 2;
      }
      
      // 遍历四叉树,将叶节点数据存储到out所指的数组中
      void __travels( QuadTree* root, Datatype** out )
      {
      	int i;
      
      	if ( root == NULL )
      		return;
      
      	if ( isLeaf( root ) )
      	{
      		if ( N >= max_leaf_num ) // 如果数组空间不足
      		{
      			expandArr( out );   // 将数组空间扩大两倍
      		}
      
      		(*out)[N++] = root->data;
      		return;
      	}
      
      	for ( i = 0; i < CHILD_NUM; ++i )
      		__travels( root->child[i], out );
      }
      
      // 遍历,返回叶节点数目
      int Travels( QuadTree* root, Datatype** out )
      {
      	N = 0;  // 全局变量,记录也节点个数
      	__travels( root, out );
      	return N;
      }
      
      // 初始化
      QuadTree* InitTree()
      {
      	int i;
      
      	QuadTree* root = (QuadTree*)malloc(sizeof(QuadTree));
      	for ( i = 0; i < CHILD_NUM; ++i )
      	{
      		root->child[i] = NULL;
      	}
      
      	return root;
      }
      
      // 释放树空间
      void ReleaseTree( QuadTree** root )
      {
      	int i;
      
      	QuadTree* node = *root;
      	if ( node == NULL ) 
      		return;
      	else
      	{
      		for ( i = 0; i < CHILD_NUM; ++i )
      		{
      			ReleaseTree( &(node->child[i]) );
      		}
      		free( node );
      	}
      
      	*root = NULL;
      }
      
      // 在root的第n个孩子处插入数据d
      void InsertData( QuadTree* root, Datatype d, int n )
      {
      	int i;
      	QuadTree* tmpNode = NULL;
      
      	if ( n < 0 || n >= 4 || root == NULL )  // 如果n不为0,1,2,3或者root为空,这直接结束
      		return;
      	if ( root->child[n] != NULL )           // 如果root的第n个孩子节点已经有数据,则用d替换该数据
      		root->child[n]->data = d;
      	else                                    // 否则,分配一个新节点,该节点数据为d,让child[n]指向该节点
      	{
      		tmpNode = (QuadTree*)malloc(sizeof(QuadTree));
      		for ( i = 0; i < CHILD_NUM; ++i )
      		{
      			tmpNode->child[i] = NULL;
      		}
      		tmpNode->data = d;
      
      		root->child[n] = tmpNode;
      	}
      }
      
      int main()
      {
      	int i;
      	QuadTree* root = InitTree();
      	root->data = 10;
      	for ( i = 0; i < CHILD_NUM-1; ++i )
      	{
      		InsertData( root, i*i, i);
      	}
      
      	for ( i = 0; i < CHILD_NUM; ++i )
      	{
      		InsertData( root->child[0], root->data + i+2, i);
      	}
      
      	Datatype* leafData = (Datatype*)malloc( sizeof(Datatype) * max_leaf_num );
      	  
      	int K = Travels( root, &leafData );
      
      	for ( int i = 0; i < K; ++i )
      	{
      		printf("%d\n", leafData[i] );
      	}
      
      	ReleaseTree( &root ); 
      
      	return 0;
      }