四叉树空间索引原理及其实现


今天依然在放假中,在此将以前在学校写的四叉树的东西拿出来和大家分享。

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

 

索引码表文件打开失败总弹出怎么办啊 索引normal_四叉树

四叉树示意图

 

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

 

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

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

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

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

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

 

索引码表文件打开失败总弹出怎么办啊 索引normal_#pragma_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. typedefenum
    15. {  
    16.     UR = 0,  
    17.     UL = 1,  
    18.     LL = 2,  
    19.     LR = 3  
    20. }QuadrantEnum;  
    21.   
    22. /*空间对象MBR信息*/
    23. typedefstruct
    24. {  
    25. int//空间对象ID号
    26. //空间对象MBR范围坐标
    27. }SHPMBRInfo;  
    28.   
    29. /* 四叉树节点类型结构 */
    30. typedefstruct
    31. {  
    32. //节点所代表的矩形区域
    33. int//节点所包含的所有空间对象个数
    34. //空间对象指针数组
    35. int//子节点个数
    36. //指向节点的四个孩子 
    37. }QuadNode;  
    38.   
    39. /* 四叉树类型结构 */
    40. typedefstruct
    41. {  
    42.     QuadNode  *root;  
    43. int// 四叉树的深度                    
    44. }QuadTree;  
    45.   
    46.   
    47. //初始化四叉树节点
    48.     QuadNode *InitQuadNode();  
    49.   
    50. //层次创建四叉树方法(满四叉树)
    51. voidint
    52.   
    53. //创建各个分支
    54. voidint
    55.   
    56. //构建四叉树空间索引
    57. void
    58.   
    59. //四叉树索引查询(矩形查询)
    60. voidint>& ItemSearched);  
    61.   
    62. //四叉树索引查询(矩形查询)并行查询
    63. voidint>& ItemSearched);  
    64.   
    65. //四叉树的查询(点查询)
    66. voiddouble cx,double cy,vector<int>& ItemSearched);  
    67.   
    68. //将指定的空间对象插入到四叉树中
    69. voidlong
    70.   
    71. //将指定的空间对象插入到四叉树中
    72. voidlong
    73.   
    74. //将指定的空间对象插入到四叉树中
    75. voidlong
    76.   
    77. //判断一个节点是否是叶子节点
    78. bool
    79.   
    80. //删除多余的节点
    81. bool
    82.   
    83. //四叉树遍历(所有要素)
    84. voidint>& resVec);  
    85.   
    86. //四叉树遍历(所有节点)
    87. void
    88.   
    89. //释放树的内存空间
    90. void
    91.   
    92. //计算四叉树所占的字节的大小
    93. longlong& nSize);  
    94.   
    95.   
    96. #endif



    源文件如下:



    [cpp]  view plain copy


    1. #include "QuadTree.h"
    2.   
    3.   
    4. QuadNode *InitQuadNode()  
    5. {  
    6. new
    7.     node->Box.maxX = 0;  
    8.     node->Box.maxY = 0;  
    9.     node->Box.minX = 0;  
    10.     node->Box.minY = 0;  
    11.   
    12. forint
    13.     {  
    14.         node->children[i] = NULL;  
    15.     }  
    16.     node->nChildCount = 0;  
    17.     node->nShpCount = 0;  
    18.     node->pShapeObj = NULL;  
    19.   
    20. return
    21. }  
    22.   
    23. voidint
    24. {  
    25.     pQuadTree->depth = depth;  
    26.   
    27. //整个图层的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
    40. new
    41. forint
    42.     {  
    43.         pFeatureClass[i] = poLayer->GetFeature(i);   
    44.     }  
    45.   
    46. //插入各个要素
    47. //空间对象的MBR
    48. //#pragma omp parallel for
    49. forint
    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. voidint
    63. {  
    64. if
    65.     {  
    66. //创建树根
    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. forint
    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
    85. {  
    86.     assert(poLayer);  
    87. //整个图层的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
    101.   
    102.     MapRect rect;  
    103. //空间对象的MBR
    104. forint
    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. voidint>& ItemSearched)  
    118. {  
    119.     assert(node);  
    120.   
    121. //int coreNum = omp_get_num_procs();
    122. //vector<int> * pResArr = new vector<int>[coreNum];
    123.   
    124. if
    125.     {  
    126. forint
    127.         {  
    128. if
    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. forint
    175.         {  
    176. if
    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. voidint>& ItemSearched)  
    194. {  
    195. int
    196.     omp_set_num_threads(coreNum);  
    197. int>* searchArrs = new vector<int>[coreNum];  
    198. forint
    199.     {  
    200.         searchArrs[i].clear();  
    201.     }  
    202.   
    203.     #pragma omp parallel for
    204. forint
    205.     {  
    206. int
    207. forint
    208.         {  
    209. if
    210.                 || queryRect.Intersects(resNodes[i]->pShapeObj[j].Box))  
    211.             {  
    212.                 searchArrs[tid].push_back(resNodes[i]->pShapeObj[j].nID);  
    213.             }  
    214.         }  
    215.     }  
    216.   
    217. forint
    218.     {  
    219.         ItemSearched.insert(ItemSearched.end(),  
    220.             searchArrs[i].begin(),searchArrs[i].end());  
    221.     }  
    222.   
    223. delete
    224.     searchArrs = NULL;  
    225. }  
    226.   
    227. voiddouble cx,double cy,vector<int>& ItemSearched)  
    228. {  
    229.     assert(node);  
    230. if//节点          
    231.     {  
    232. forint
    233.         {  
    234. if
    235.             {  
    236.                 ItemSearched.push_back(node->pShapeObj[i].nID);  
    237.             }  
    238.         }  
    239.     }  
    240.   
    241. elseif (node->nChildCount >0)                //节点
    242.     {  
    243. forint
    244.         {  
    245. if
    246.             {  
    247.                 PtSearchQTree(node->children[i],cx,cy,ItemSearched);  
    248.             }  
    249.         }  
    250.     }  
    251.   
    252. //找出重复元素的位置
    253. //先排序,默认升序
    254. int>::iterator unique_iter =   
    255.         unique(ItemSearched.begin(),ItemSearched.end());  
    256.     ItemSearched.erase(unique_iter,ItemSearched.end());  
    257. }  
    258.   
    259. voidlong
    260. {  
    261. //保留根节点副本
    262.     SHPMBRInfo pShpInfo;  
    263.       
    264. //节点有孩子
    265. if
    266.     {  
    267. forint
    268.         {    
    269. //如果包含或相交,则将节点插入到此节点
    270. if
    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. elseif
    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. forint
    298.         {    
    299. //将当前节点中的要素移动到相应的子节点中
    300. forint
    301.             {  
    302. if
    303.                     || node->children[i]->Box.Intersects(node->pShapeObj[j].Box))  
    304.                 {  
    305.                     node->children[i]->nShpCount += 1;  
    306.                     node->children[i]->pShapeObj =   
    307. sizeof(SHPMBRInfo));  
    308.                       
    309. sizeof(SHPMBRInfo));  
    310.   
    311.                     free(node->pShapeObj);  
    312.                     node->pShapeObj = NULL;  
    313.                     node->nShpCount = 0;  
    314.                 }  
    315.             }  
    316.         }  
    317.   
    318. forint
    319.         {    
    320. //如果包含或相交,则将节点插入到此节点
    321. if
    322.                 || node->children[i]->Box.Intersects(itemRect))  
    323.             {  
    324. if//如果之前没有节点
    325.                 {  
    326.                     node->children[i]->nShpCount += 1;  
    327.                     node->pShapeObj =   
    328. sizeof(SHPMBRInfo)*node->children[i]->nShpCount);  
    329.                 }  
    330. elseif
    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. sizeof(SHPMBRInfo));  
    342.             }  
    343.         }  
    344.     }  
    345.   
    346. //当前节点没有空间对象
    347. elseif
    348.     {  
    349.         node->nShpCount += 1;  
    350.         node->pShapeObj =   
    351. sizeof(SHPMBRInfo)*node->nShpCount);  
    352.   
    353.         pShpInfo.Box = itemRect;  
    354.         pShpInfo.nID = key;  
    355. sizeof(SHPMBRInfo));  
    356.     }  
    357. }  
    358.   
    359. voidlong
    360. {  
    361.     assert(pNode != NULL);  
    362.   
    363. if//非叶子节点
    364.     {  
    365. int//跨越的子节点个数
    366. int//被哪个子节点完全包含的索引号
    367. forint
    368.         {  
    369. if
    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. elseif
    386.         {  
    387. if//如果之前没有节点
    388.             {  
    389.                 pNode->nShpCount += 1;  
    390.                 pNode->pShapeObj =   
    391. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    392.             }  
    393. else
    394.             {  
    395.                 pNode->nShpCount += 1;  
    396.                 pNode->pShapeObj =   
    397. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    398.             }  
    399.   
    400.             SHPMBRInfo pShpInfo;  
    401.             pShpInfo.Box = itemRect;  
    402.             pShpInfo.nID = key;  
    403. sizeof(SHPMBRInfo));  
    404.         }  
    405.     }  
    406.   
    407. //如果是叶子节点,直接放进去
    408. elseif
    409.     {  
    410. if//如果之前没有节点
    411.         {  
    412.             pNode->nShpCount += 1;  
    413.             pNode->pShapeObj =   
    414. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    415.         }  
    416. else
    417.         {  
    418.             pNode->nShpCount += 1;  
    419.             pNode->pShapeObj =   
    420. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    421.         }  
    422.   
    423.         SHPMBRInfo pShpInfo;  
    424.         pShpInfo.Box = itemRect;  
    425.         pShpInfo.nID = key;  
    426. sizeof(SHPMBRInfo));  
    427.     }  
    428. }  
    429.   
    430. voidlong
    431. {  
    432. //保留根节点副本
    433.     SHPMBRInfo pShpInfo;  
    434.   
    435. //节点有孩子
    436. if
    437.     {  
    438. forint
    439.         {    
    440. //如果包含或相交,则将节点插入到此节点
    441. if
    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. elseif
    452.     {  
    453.         MapRect boxs[4];  
    454.         node->Box.Split(boxs,boxs+1,boxs+2,boxs+3);  
    455.   
    456. int
    457. forint
    458.         {    
    459. //如果包含或相交,则将节点插入到此节点
    460. if
    461.             {  
    462.                 cnt = i;  
    463.             }  
    464.         }  
    465.   
    466. //如果有一个矩形包含此对象,则创建四个孩子节点
    467. if
    468.         {  
    469. forint
    470.             {  
    471. //创建四个节点并插入相应的MBR
    472.                 node->children[i] = InitQuadNode();  
    473.                 node->children[i]->Box = boxs[i];  
    474.             }  
    475.             node->nChildCount = 4;  
    476. //递归
    477.         }  
    478.   
    479. //如果都不包含,则直接将对象插入此节点
    480. if
    481.         {  
    482. if//如果之前没有节点
    483.             {  
    484.                 node->nShpCount += 1;  
    485.                 node->pShapeObj =   
    486. sizeof(SHPMBRInfo)*node->nShpCount);  
    487.             }  
    488. elseif
    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. 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
    517. {  
    518. if
    519.     {  
    520. return
    521.     }  
    522. forint
    523.     {  
    524. if
    525.         {  
    526. return
    527.         }  
    528.     }  
    529.   
    530. return
    531. }  
    532.   
    533. bool
    534. {  
    535. //如果没有子节点且没有要素
    536. if
    537.     {  
    538.         ReleaseQuadTree(&node);  
    539.     }  
    540.   
    541. //如果有子节点
    542. elseif
    543.     {  
    544. forint
    545.         {  
    546.             DelFalseNode(node->children[i]);  
    547.         }  
    548.     }  
    549.   
    550. return
    551. }  
    552.   
    553. voidint>& resVec)  
    554. {  
    555.     QuadNode *node = quadTree;  
    556. int
    557. if
    558.     {  
    559. //将本节点中的空间对象存储数组中
    560. for
    561.         {  
    562.             resVec.push_back((node->pShapeObj+i)->nID);  
    563.         }  
    564.   
    565. //遍历孩子节点
    566. for
    567.         {  
    568. if
    569.             {  
    570.                 TraversalQuadTree(node->children[i],resVec);  
    571.             }  
    572.         }  
    573.     }  
    574.   
    575. }  
    576.   
    577. void
    578. {  
    579.     deque<QuadNode*> nodeQueue;  
    580. if
    581.     {  
    582.         nodeQueue.push_back(quadTree);  
    583. while
    584.         {  
    585. //取队列头结点
    586.             arrNode.push_back(queueHead);  
    587.             nodeQueue.pop_front();  
    588. forint
    589.             {  
    590. if
    591.                 {  
    592.                     nodeQueue.push_back(queueHead->children[i]);  
    593.                 }  
    594.             }  
    595.         }  
    596.     }  
    597. }  
    598.   
    599. void
    600. {  
    601. int
    602.     QuadNode* node = *quadTree;  
    603. if
    604.     {  
    605. return;  
    606.     }  
    607.   
    608. else
    609.     {  
    610. for
    611.         {   
    612.             ReleaseQuadTree(&node->children[i]);  
    613.         }  
    614.         free(node);  
    615.         node = NULL;  
    616.     }  
    617.   
    618.     node = NULL;  
    619. }  
    620.   
    621. longlong& nSize)  
    622. {  
    623. if
    624.     {  
    625. sizeof(QuadNode)+quadTree->nChildCount*sizeof(SHPMBRInfo);  
    626. forint
    627.         {  
    628. if
    629.             {  
    630.                 nSize += CalByteQuadTree(quadTree->children[i],nSize);  
    631.             }  
    632.         }  
    633.     }  
    634.   
    635. return
    636. }



    代码有点长,有需要的朋友可以借鉴并自己优化


    今天依然在放假中,在此将以前在学校写的四叉树的东西拿出来和大家分享。

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

     

    索引码表文件打开失败总弹出怎么办啊 索引normal_四叉树

    四叉树示意图

     

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

     

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

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

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

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

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

     

    索引码表文件打开失败总弹出怎么办啊 索引normal_#pragma_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. typedefenum
    15. {  
    16.     UR = 0,  
    17.     UL = 1,  
    18.     LL = 2,  
    19.     LR = 3  
    20. }QuadrantEnum;  
    21.   
    22. /*空间对象MBR信息*/
    23. typedefstruct
    24. {  
    25. int//空间对象ID号
    26. //空间对象MBR范围坐标
    27. }SHPMBRInfo;  
    28.   
    29. /* 四叉树节点类型结构 */
    30. typedefstruct
    31. {  
    32. //节点所代表的矩形区域
    33. int//节点所包含的所有空间对象个数
    34. //空间对象指针数组
    35. int//子节点个数
    36. //指向节点的四个孩子 
    37. }QuadNode;  
    38.   
    39. /* 四叉树类型结构 */
    40. typedefstruct
    41. {  
    42.     QuadNode  *root;  
    43. int// 四叉树的深度                    
    44. }QuadTree;  
    45.   
    46.   
    47. //初始化四叉树节点
    48.     QuadNode *InitQuadNode();  
    49.   
    50. //层次创建四叉树方法(满四叉树)
    51. voidint
    52.   
    53. //创建各个分支
    54. voidint
    55.   
    56. //构建四叉树空间索引
    57. void
    58.   
    59. //四叉树索引查询(矩形查询)
    60. voidint>& ItemSearched);  
    61.   
    62. //四叉树索引查询(矩形查询)并行查询
    63. voidint>& ItemSearched);  
    64.   
    65. //四叉树的查询(点查询)
    66. voiddouble cx,double cy,vector<int>& ItemSearched);  
    67.   
    68. //将指定的空间对象插入到四叉树中
    69. voidlong
    70.   
    71. //将指定的空间对象插入到四叉树中
    72. voidlong
    73.   
    74. //将指定的空间对象插入到四叉树中
    75. voidlong
    76.   
    77. //判断一个节点是否是叶子节点
    78. bool
    79.   
    80. //删除多余的节点
    81. bool
    82.   
    83. //四叉树遍历(所有要素)
    84. voidint>& resVec);  
    85.   
    86. //四叉树遍历(所有节点)
    87. void
    88.   
    89. //释放树的内存空间
    90. void
    91.   
    92. //计算四叉树所占的字节的大小
    93. longlong& nSize);  
    94.   
    95.   
    96. #endif
     
     
     源文件如下:
     
     
     
        [cpp]  
        view plain 
        copy 
       
     
      
    1. #include "QuadTree.h"
    2.   
    3.   
    4. QuadNode *InitQuadNode()  
    5. {  
    6. new
    7.     node->Box.maxX = 0;  
    8.     node->Box.maxY = 0;  
    9.     node->Box.minX = 0;  
    10.     node->Box.minY = 0;  
    11.   
    12. forint
    13.     {  
    14.         node->children[i] = NULL;  
    15.     }  
    16.     node->nChildCount = 0;  
    17.     node->nShpCount = 0;  
    18.     node->pShapeObj = NULL;  
    19.   
    20. return
    21. }  
    22.   
    23. voidint
    24. {  
    25.     pQuadTree->depth = depth;  
    26.   
    27. //整个图层的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
    40. new
    41. forint
    42.     {  
    43.         pFeatureClass[i] = poLayer->GetFeature(i);   
    44.     }  
    45.   
    46. //插入各个要素
    47. //空间对象的MBR
    48. //#pragma omp parallel for
    49. forint
    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. voidint
    63. {  
    64. if
    65.     {  
    66. //创建树根
    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. forint
    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
    85. {  
    86.     assert(poLayer);  
    87. //整个图层的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
    101.   
    102.     MapRect rect;  
    103. //空间对象的MBR
    104. forint
    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. voidint>& ItemSearched)  
    118. {  
    119.     assert(node);  
    120.   
    121. //int coreNum = omp_get_num_procs();
    122. //vector<int> * pResArr = new vector<int>[coreNum];
    123.   
    124. if
    125.     {  
    126. forint
    127.         {  
    128. if
    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. forint
    175.         {  
    176. if
    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. voidint>& ItemSearched)  
    194. {  
    195. int
    196.     omp_set_num_threads(coreNum);  
    197. int>* searchArrs = new vector<int>[coreNum];  
    198. forint
    199.     {  
    200.         searchArrs[i].clear();  
    201.     }  
    202.   
    203.     #pragma omp parallel for
    204. forint
    205.     {  
    206. int
    207. forint
    208.         {  
    209. if
    210.                 || queryRect.Intersects(resNodes[i]->pShapeObj[j].Box))  
    211.             {  
    212.                 searchArrs[tid].push_back(resNodes[i]->pShapeObj[j].nID);  
    213.             }  
    214.         }  
    215.     }  
    216.   
    217. forint
    218.     {  
    219.         ItemSearched.insert(ItemSearched.end(),  
    220.             searchArrs[i].begin(),searchArrs[i].end());  
    221.     }  
    222.   
    223. delete
    224.     searchArrs = NULL;  
    225. }  
    226.   
    227. voiddouble cx,double cy,vector<int>& ItemSearched)  
    228. {  
    229.     assert(node);  
    230. if//节点          
    231.     {  
    232. forint
    233.         {  
    234. if
    235.             {  
    236.                 ItemSearched.push_back(node->pShapeObj[i].nID);  
    237.             }  
    238.         }  
    239.     }  
    240.   
    241. elseif (node->nChildCount >0)                //节点
    242.     {  
    243. forint
    244.         {  
    245. if
    246.             {  
    247.                 PtSearchQTree(node->children[i],cx,cy,ItemSearched);  
    248.             }  
    249.         }  
    250.     }  
    251.   
    252. //找出重复元素的位置
    253. //先排序,默认升序
    254. int>::iterator unique_iter =   
    255.         unique(ItemSearched.begin(),ItemSearched.end());  
    256.     ItemSearched.erase(unique_iter,ItemSearched.end());  
    257. }  
    258.   
    259. voidlong
    260. {  
    261. //保留根节点副本
    262.     SHPMBRInfo pShpInfo;  
    263.       
    264. //节点有孩子
    265. if
    266.     {  
    267. forint
    268.         {    
    269. //如果包含或相交,则将节点插入到此节点
    270. if
    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. elseif
    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. forint
    298.         {    
    299. //将当前节点中的要素移动到相应的子节点中
    300. forint
    301.             {  
    302. if
    303.                     || node->children[i]->Box.Intersects(node->pShapeObj[j].Box))  
    304.                 {  
    305.                     node->children[i]->nShpCount += 1;  
    306.                     node->children[i]->pShapeObj =   
    307. sizeof(SHPMBRInfo));  
    308.                       
    309. sizeof(SHPMBRInfo));  
    310.   
    311.                     free(node->pShapeObj);  
    312.                     node->pShapeObj = NULL;  
    313.                     node->nShpCount = 0;  
    314.                 }  
    315.             }  
    316.         }  
    317.   
    318. forint
    319.         {    
    320. //如果包含或相交,则将节点插入到此节点
    321. if
    322.                 || node->children[i]->Box.Intersects(itemRect))  
    323.             {  
    324. if//如果之前没有节点
    325.                 {  
    326.                     node->children[i]->nShpCount += 1;  
    327.                     node->pShapeObj =   
    328. sizeof(SHPMBRInfo)*node->children[i]->nShpCount);  
    329.                 }  
    330. elseif
    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. sizeof(SHPMBRInfo));  
    342.             }  
    343.         }  
    344.     }  
    345.   
    346. //当前节点没有空间对象
    347. elseif
    348.     {  
    349.         node->nShpCount += 1;  
    350.         node->pShapeObj =   
    351. sizeof(SHPMBRInfo)*node->nShpCount);  
    352.   
    353.         pShpInfo.Box = itemRect;  
    354.         pShpInfo.nID = key;  
    355. sizeof(SHPMBRInfo));  
    356.     }  
    357. }  
    358.   
    359. voidlong
    360. {  
    361.     assert(pNode != NULL);  
    362.   
    363. if//非叶子节点
    364.     {  
    365. int//跨越的子节点个数
    366. int//被哪个子节点完全包含的索引号
    367. forint
    368.         {  
    369. if
    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. elseif
    386.         {  
    387. if//如果之前没有节点
    388.             {  
    389.                 pNode->nShpCount += 1;  
    390.                 pNode->pShapeObj =   
    391. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    392.             }  
    393. else
    394.             {  
    395.                 pNode->nShpCount += 1;  
    396.                 pNode->pShapeObj =   
    397. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    398.             }  
    399.   
    400.             SHPMBRInfo pShpInfo;  
    401.             pShpInfo.Box = itemRect;  
    402.             pShpInfo.nID = key;  
    403. sizeof(SHPMBRInfo));  
    404.         }  
    405.     }  
    406.   
    407. //如果是叶子节点,直接放进去
    408. elseif
    409.     {  
    410. if//如果之前没有节点
    411.         {  
    412.             pNode->nShpCount += 1;  
    413.             pNode->pShapeObj =   
    414. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    415.         }  
    416. else
    417.         {  
    418.             pNode->nShpCount += 1;  
    419.             pNode->pShapeObj =   
    420. sizeof(SHPMBRInfo)*pNode->nShpCount);  
    421.         }  
    422.   
    423.         SHPMBRInfo pShpInfo;  
    424.         pShpInfo.Box = itemRect;  
    425.         pShpInfo.nID = key;  
    426. sizeof(SHPMBRInfo));  
    427.     }  
    428. }  
    429.   
    430. voidlong
    431. {  
    432. //保留根节点副本
    433.     SHPMBRInfo pShpInfo;  
    434.   
    435. //节点有孩子
    436. if
    437.     {  
    438. forint
    439.         {    
    440. //如果包含或相交,则将节点插入到此节点
    441. if
    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. elseif
    452.     {  
    453.         MapRect boxs[4];  
    454.         node->Box.Split(boxs,boxs+1,boxs+2,boxs+3);  
    455.   
    456. int
    457. forint
    458.         {    
    459. //如果包含或相交,则将节点插入到此节点
    460. if
    461.             {  
    462.                 cnt = i;  
    463.             }  
    464.         }  
    465.   
    466. //如果有一个矩形包含此对象,则创建四个孩子节点
    467. if
    468.         {  
    469. forint
    470.             {  
    471. //创建四个节点并插入相应的MBR
    472.                 node->children[i] = InitQuadNode();  
    473.                 node->children[i]->Box = boxs[i];  
    474.             }  
    475.             node->nChildCount = 4;  
    476. //递归
    477.         }  
    478.   
    479. //如果都不包含,则直接将对象插入此节点
    480. if
    481.         {  
    482. if//如果之前没有节点
    483.             {  
    484.                 node->nShpCount += 1;  
    485.                 node->pShapeObj =   
    486. sizeof(SHPMBRInfo)*node->nShpCount);  
    487.             }  
    488. elseif
    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. 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
    517. {  
    518. if
    519.     {  
    520. return
    521.     }  
    522. forint
    523.     {  
    524. if
    525.         {  
    526. return
    527.         }  
    528.     }  
    529.   
    530. return
    531. }  
    532.   
    533. bool
    534. {  
    535. //如果没有子节点且没有要素
    536. if
    537.     {  
    538.         ReleaseQuadTree(&node);  
    539.     }  
    540.   
    541. //如果有子节点
    542. elseif
    543.     {  
    544. forint
    545.         {  
    546.             DelFalseNode(node->children[i]);  
    547.         }  
    548.     }  
    549.   
    550. return
    551. }  
    552.   
    553. voidint>& resVec)  
    554. {  
    555.     QuadNode *node = quadTree;  
    556. int
    557. if
    558.     {  
    559. //将本节点中的空间对象存储数组中
    560. for
    561.         {  
    562.             resVec.push_back((node->pShapeObj+i)->nID);  
    563.         }  
    564.   
    565. //遍历孩子节点
    566. for
    567.         {  
    568. if
    569.             {  
    570.                 TraversalQuadTree(node->children[i],resVec);  
    571.             }  
    572.         }  
    573.     }  
    574.   
    575. }  
    576.   
    577. void
    578. {  
    579.     deque<QuadNode*> nodeQueue;  
    580. if
    581.     {  
    582.         nodeQueue.push_back(quadTree);  
    583. while
    584.         {  
    585. //取队列头结点
    586.             arrNode.push_back(queueHead);  
    587.             nodeQueue.pop_front();  
    588. forint
    589.             {  
    590. if
    591.                 {  
    592.                     nodeQueue.push_back(queueHead->children[i]);  
    593.                 }  
    594.             }  
    595.         }  
    596.     }  
    597. }  
    598.   
    599. void
    600. {  
    601. int
    602.     QuadNode* node = *quadTree;  
    603. if
    604.     {  
    605. return;  
    606.     }  
    607.   
    608. else
    609.     {  
    610. for
    611.         {   
    612.             ReleaseQuadTree(&node->children[i]);  
    613.         }  
    614.         free(node);  
    615.         node = NULL;  
    616.     }  
    617.   
    618.     node = NULL;  
    619. }  
    620.   
    621. longlong& nSize)  
    622. {  
    623. if
    624.     {  
    625. sizeof(QuadNode)+quadTree->nChildCount*sizeof(SHPMBRInfo);  
    626. forint
    627.         {  
    628. if
    629.             {  
    630.                 nSize += CalByteQuadTree(quadTree->children[i],nSize);  
    631.             }  
    632.         }  
    633.     }  
    634.   
    635. return
    636. }

    代码有点长,有需要的朋友可以借鉴并自己优化