四叉树算法
title: 四叉树算法
date: 2016-1-11 15:10
categories: IOS
tags: 算法
四叉树或四元树也被称为Q树(Q-Tree)。四叉树⼴泛应⽤于图像处理、空间数据索引、2D中的快速碰撞检测、存储稀疏数据等,⽽⼋叉树(Octree)主要应⽤于3D图形处理。对游戏编程,这会很有⽤。本⽂着重于对四叉树与⼋叉树的原理与结构的介绍,帮助您在脑海中建⽴四叉树与⼋叉树的基本思想。本⽂并不对这两种数据结构同时进⾏详解,⽽只对四叉树进⾏详解,因为⼋叉树的建⽴可由四叉树的建⽴推得。
四叉树与⼋叉树的结构与原理
四叉树(Q-Tree)是⼀种树形数据结构。四叉树的定义是:它的每个节点下⾄多可以有四个⼦节点,通常把⼀部分⼆维空间细分为四个象限或区域并把该区域⾥的相关信息存⼊到四叉树节点中。这个区域可
以是正⽅形、矩形或是任意形状。以下为四叉树的⼆维空间结构(左)和存储结构(右)⽰意图(注意节点颜⾊与⽹格边框颜⾊):
四叉树的每⼀个节点代表⼀个矩形区域(如上图⿊⾊的根节点代表最外围⿊⾊边框的矩形区域),每⼀个矩形区域⼜可划分为四个⼩矩形区域,这四个⼩矩形区域作为四个⼦节点所代表的矩形区域。
较之四叉树,⼋叉树将场景从⼆维空间延伸到了三维空间。⼋叉树(Octree)的定义是:若不为空树的话,树中任⼀节点的⼦节点恰好只会有⼋个,或零个,也就是⼦节点不会有0与8以外的数⽬。那么,这要⽤来做什么?想象⼀个⽴⽅体,我们最少可以切成多少个相同等分的⼩⽴⽅体?答案就是8个。如下⼋叉树的结构⽰意图所⽰:
英语四级单词表
/* ⼀个矩形区域的象限划分::
UL(1) | UR(0)
----------|-----------
LL(2) | LR(3)
以下对该象限类型的枚举
*/
typedef enum
{
UR = 0,
UL = 1,
LL = 2,
LR = 3
}QuadrantEnum;
/* 矩形结构 */
typedef struct quadrect_t
h p{
intervention
double left,
top,
right,
bottom;
wh}quadrect_t;
/* 四叉树节点类型结构 */
rid
typedef struct quadnode_t
刺客联盟片尾曲
{
quadrect_t rect; //节点所代表的矩形区域
list_t *lst_object; //节点数据, 节点类型⼀般为链表,可存储多个对象
struct quadnode_t *sub[4]; //指向节点的四个孩⼦
}quadnode_t;
翻唱达人/* 四叉树类型结构 */
typedef struct quadtree_t
{
quadnode_t *root;
int depth; // 四叉树的深度
}quadtree_t;
四叉树的建⽴
利⽤四叉树分⽹格,如本⽂的第⼀张图<;四层完全四叉树结构⽰意图>,根据左图的⽹格图形建⽴如右图所⽰的完全四叉树。伪码:
Funtion QuadTreeBuild ( depth, rect )
{
QuadTree->depth = depth;
/*创建分⽀,root树的根,depth深度,rect根节点代表的矩形区域*/
QuadCreateBranch ( root, depth, rect );
}
Funtion QuadCreateBranch ( n, depth,rect )
{
if ( depth!=0 )
{
n = new node; //开辟新节点
n ->rect = rect; //将该节点所代表的矩形区域存储到该节点中publishers
将rect划成四份 rect[UR], rect[UL], rect[LL], rect[LR];
/
*创建各孩⼦分⽀*/
QuadCreateBranch ( n->sub[UR], depth-1, rect [UR] );
QuadCreateBranch ( n->sub[UL], depth-1, rect [UL] );
QuadCreateBranch ( n->sub[LL], depth-1, rect [LL] );
QuadCreateBranch ( n->sub[LR], depth-1, rect [LR] );
}
}
假设在⼀个矩形区域⾥有N个对象,如下左图⼀个⿊点代表⼀个对象,每个对象的坐标位置都是已知的,⽤四叉树的⼀个节点存储⼀个对象,构建成如下右图所⽰的四叉树。
⽅法也是采⽤递归的⽅法对该矩形进⾏划分分区块,分完后再往⾥分,直到每⼀个⼦矩形区域⾥只包含⼀个对象为⽌。
伪码:
Funtion QuadtreeBuild()
{
Quadtree = {empty};
For (i = 1;i<n;i++) //遍历所有对象
{
QuadInrt(i, root);//将i对象插⼊四叉树
}
剔除多余的节点; //执⾏完上⾯循环后,四叉树中可能有数据为空的叶⼦节点需要剔除
}
Funtion QuadInrt(i,n) //该函数插⼊后四叉树中的每个节点所存储的对象数量不是1就是0
{
if(节点n有孩⼦)
{
通过划分区域判断i应该放置于n节点的哪⼀个孩⼦节点c;
QuadInrt(i,c);
}
el if(节点n存储了⼀个对象)
{
为n节点创建四个孩⼦;
将n节点中的对象移到它应该放置的孩⼦节点中;
通过划分区域判断i应该放置于n节点的哪⼀个孩⼦节点c;
QuadInrt(i,c);
}
el if(n节点数据为空)
{
将i存储到节点n中;
}
fullscale}
⽤四叉树查找某⼀对象
1、采⽤盲⽬搜索,与⼆叉树的递归遍历类似,可采⽤后序遍历或前序遍历或中序遍历对其进⾏搜索某⼀对象,时间复杂度为O(n)。
2、根据对象在区域⾥的位置来搜索,采⽤分⽽治之思想,时间复杂度只与四叉树的深度有关。⽐起盲⽬搜索,这种搜索在区域⾥的对象越多时效果越明显
Funtion find ( n, pos, )
threesome{
If (n节点所存的对象位置为 pos所指的位置 )
Return n;
If ( pos位于第⼀象限 )
temp = find ( n->sub[UR], pos );
el if ( pos位于第⼆象限)
temp = find ( n->sub[UL], pos );
el if ( pos位于第三象限 )
temp = find ( n->sub[LL], pos );
el //pos 位于第四象限
temp = find ( n->sub[LR], pos );
return temp;
}