四叉树原理

最近利用OpenGL实现了一个简单的四叉树,对窗口进行分割。

数据结构:


  1. AreaType m_bounds;  
    rectContainer m_contents;     
    pointerType m_nodes[4];  

m_bounds是节点的矩形包围盒, m_nodes数组存储四个孩子的节点指针, m_contents存储那些不包含于四个孩子但是包含于当前节点的区域,也就是那些我们插入的区域(假设使用的是矩形)。

如下图:是一个节点的内容:

 

 

 

 

 

写成一般的树状图是:

 

 


算法描述:

插入一个矩形区域到四叉树中

1 将当前节点细分,添加四个孩子节点:

 

m_nodes[LUp] = new QuadTreeNode( TRectanglef(m_bounds.GetPos(),   
        Vec2f(halfWidth, halfHeight)) );  
m_nodes[LDown] = new QuadTreeNode( TRectanglef(Vec2f(m_bounds.m_Left,   
        m_bounds.m_Top + halfHeight), Vec2f(halfWidth, halfHeight)) );  
m_nodes[RUp] = new QuadTreeNode( TRectanglef(Vec2f(m_bounds.m_Left + halfWidth,   
        m_bounds.m_Top), Vec2f(halfWidth, halfHeight)) );  
m_nodes[RDown] = new QuadTreeNode( TRectanglef(   
        Vec2f(m_bounds.m_Left + halfWidth,   
        m_bounds.m_Top + halfHeight), Vec2f(halfWidth, halfHeight)) );  


2 如果要插入的矩形属于区域某个孩子节点,则递归深入,继续细分该孩子节点。

3 直到该区域不属于任何孩子节点时候,直接存放到当前节点的content数组中。

 

查询一个矩形区域在四叉树中:

返回所有与该区域相交或者包含的区域,以一个vector的新式。

程序截图:

标左键拖出椭圆,区域同时将这些区域插入到四叉树中:

 

 

右键拖出一个白色框选择区域,进行查询:

查询结果为:

 

 

这里没法上传文件。具体demo可以到我的资源里下载。

<think>嗯,用户想了解线性四叉树原理和概念。用户之前可能接触过四叉树的基础知识,现在想深入理解线性存储版本的特殊实现。 用户提供的引用材料很有价值。引用[1]提到线性八叉树"节省存贮空间但丧失灵活性",这其实暗示了线性四叉树的核心特点——用一维结构存储二维空间数据。引用[2][3]则补充了四叉树的基础概念和GIS应用背景。看来用户需要的是原理性解释而非代码实现。 线性四叉树的关键在于空间填充曲线。我决定从莫顿码这个最常用的编码方式切入,因为: 1)它直接关联二维坐标到一维编码的转换 2)用户提到的"十进制编码"在引用[2]出现,需要澄清实际是二进制操作 3)莫顿排序能自然引出存储优势 需要特别注意用户可能混淆的概念点: - "线性"指存储结构而非数据结构本质 - 十进制编码本质是二进制位的交叉 - 区域查询效率问题(引用[1]提到的遍历缺陷) 准备用二维网格的编码示例说明原理,再对比普通指针式四叉树突出优势(内存连续)和代价(查询不灵活)。最后补充GIS应用场景呼应引用[3],这样能形成闭环解释。 用户可能是GIS开发者或计算机图形学学习者,提问很精准。不过"原理"这个诉求比较宽泛,后续问题可以引导向具体方向:比如编码实现细节,或空间索引的比较选择。</think>线性四叉树的核心原理是将传统树状结构的四叉树**扁平化为一维线性存储**,通过**空间填充曲线(如莫顿码)** 对空间单元进行**唯一编码**,实现高效存储和范围查询。以下是其关键原理和概念: --- ### **一、核心原理** 1. **空间划分与编码** - 将二维空间递归划分为 **$2^n \times 2^n$** 个网格(如 $4\times4$、$8\times8$)。 - 每个网格单元赋予一个**唯一整数编码**(如莫顿码/Z序曲线),该编码通过**行列坐标的二进制位交叉**生成。 *示例(4×4网格):* | 坐标 (0,0) → 二进制 `00|00` → 莫顿码 **`0000` (0)** | 坐标 (1,3) → 二进制 `01|11` → 莫顿码 **`0111` (7)** *公式:* 若行列坐标为 $(x,y)$,二进制为 $(x_k...x_0)_2$, $(y_k...y_0)_2$,则莫顿码为 $(y_k x_k ... y_0 x_0)_2$。 2. **线性存储结构** - 所有网格单元按**编码值升序排列**,存储为连续数组(如下图),无需指针链接子节点。 ```plaintext 编码: [0, 1, 2, 3, 4, 5, 6, 7, ... , 15] 对应网格: (0,0), (0,1), (1,0), (1,1), (0,2), ... , (3,3) ``` 3. **区域查询** - 查询区域转换为**编码范围**,通过二分查找快速定位区间。 *例如:查询左下角区域(编码0-3)只需扫描数组前4项。* --- ### **二、关键概念** 1. **空间填充曲线的作用** - 莫顿码将邻近空间单元映射到邻近编码值,保持**空间局部性**(如右下角单元编码集中)。 - 但代价是**非邻近区域可能编码跳跃**(如右上角单元需遍历其他区域)[^1]。 2. **与传统指针式四叉树的对比** | **特性** | **线性四叉树** | **指针式四叉树** | |----------------|--------------------------------|--------------------------| | **存储结构** | 一维数组 | 树节点(含子节点指针) | | **存储开销** | 极小(仅存编码+数据) | 较大(额外指针开销) | | **查询灵活性** | 受限(依赖编码范围)[^1] | 灵活(可任意遍历子树) | | **构建速度** | 快(直接计算编码) | 慢(递归划分) | 3. **优化与局限** - **优势**:内存紧凑、缓存友好、批量操作高效(如大规模GIS栅格数据处理)[^3]。 - **局限**:动态更新困难(插入/删除需重建数组);复杂范围查询(如L形区域)效率低[^1]。 --- ### **三、应用场景** 1. **地理信息系统(GIS)** - 存储卫星影像、数字高程模型等栅格数据,快速定位地理区块[^3]。 2. **图像处理** - 支持基于区域的图像压缩(如JPEG2000中的四分块编码)。 3. **游戏开发** - 大规模地形渲染中的细节层次(LOD)管理。 --- ### **相关问题** 1. **莫顿码如何实现行列坐标的二进制位交叉?能否用数学公式描述?** > *提示:若行列坐标为 $(x,y)$,二进制展开为 $x = \sum_{i=0}^{k} b_i \cdot 2^i$, $y = \sum_{i=0}^{k} c_i \cdot 2^i$,则莫顿码 $m = \sum_{i=0}^{k} (c_i \cdot 2^{2i} + b_i \cdot 2^{2i+1})$。* 2. **线性四叉树在动态更新(如插入/删除节点)时为何效率较低?有哪些改进方案?** > *提示:考虑数组的连续存储特性与重建成本,可对比B+树的动态调整策略。* 3. **在GIS中,线性四叉树与R树索引有何性能差异?各自适合什么场景?** > *提示:R树擅长管理不规则多边形和频繁更新的数据,而线性四叉树更适合静态栅格数据[^3]。* [^1]: 线性结构需顺序遍历非邻近区域,导致特定查询效率降低。 [^2]: 莫顿码本质是二进制交叉,十进制编码是其数值形式。 [^3]: GIS中四叉树索引适用于规则网格数据的快速检索。
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值