C语言实现一个四叉树quadtree

C语言实现一个四叉树quadtree

cheungmine

用C语言实现一个2维四叉树quadtree,具有一定的实际意义。你可以把几何图形的索引(用long型的id标识)放到这个树中(根据最小边界矩形)。quadtree可以用来快速区域查找图形,虽然不是那么精确,但是毕竟没有漏掉的。虽然quadtree的效率不如RTree?但是RTree的实现毕竟复杂了些,我会尽快收集整理出RTree的代码。RTree确实比QuadTree好的多?(起码RTree很时髦啊!)

头文件如下:

/*
*quadtree.h
*Quadtreestructure--forspatialquicksearching
*cheungmine
*Oct.5,2007.Allrightsreserved.
*/
#ifndefQUADTREE_H_INCLUDED
#define QUADTREE_H_INCLUDED

#include
" unistd.h "

#include
" list.h "

#define QUAD_SUBNODES4

#define QBOX_OVERLAP_MAX0.4
#define QBOX_OVERLAP_MIN0.02

#define QTREE_DEPTH_MAX8
#define QTREE_DEPTH_MIN4

#define QUADRANT_BITS3

/* aquadrantdefinedbelow:

NW(1)|NE(0)
-----------|-----------
SW(2)|SE(3)
*/
typedef
enum
{
NE
= 0 ,
NW
= 1 ,
SW
= 2 ,
SE
= 3
}QuadrantEnum;

/* aboxdefinedbelow:
_____max
|__|__|
|__|__|
min
*/
typedef
struct _quadbox_t
{
double _xmin,
_ymin,
_xmax,
_ymax;
}quadbox_t;

/* quadnode */
typedef
struct _quadnode_t
{
quadbox_t_box;
/* nodeboundbox */
list_t
* _lst; /* nodedatalist */
struct _quadnode_t * _sub[QUAD_SUBNODES]; /* pointertosubnodesofthisnode */
}quadnode_t;

/* quadtree */
typedef
struct _quadtree_t
{
quadnode_t
* _root;
int _depth; /* maxdepthoftree:0-based */
float _overlap; /* overlappedratioofquanbox */
}quadtree_t;


/* =============================================================================
PublicFunctions
=============================================================================
*/
/* createsaquadtreeandreturnsapointertoit */
extern quadtree_t *
quadtree_create(quadbox_tbox,
int depth, /* 4~8 */
float overlap /* 0.02~0.4 */
);

/* destroysaquadtreeandfreeallmemory */
extern void
quadtree_destroy(INquadtree_t
* qtree
);

/* insertsanodeidentifiedbynode_keyintoaquadtree,returnsthenodequadtreeencoding */
extern quadnode_t *
quadtree_insert(INquadtree_t
* qtree,
IN
long node_key,
INquadbox_t
* node_box
);

/* searchesnodesinsidesearch_box */
extern void
quadtree_search(IN
const quadtree_t * qtree,
INquadbox_t
* search_box,
OUTlist_t
* results_list
);

#endif // QUADTREE_H_INCLUDED

实现文件如下:

/*
*quadtree.c
*Quadtreeimplementation--forspatialquicksearching
*cheungmine
*Oct.5,2007.Allrightsreserved.
*/
#include
" quadtree.h "
#include
< assert.h >

/* =============================================================================
PrivateFunctions
=============================================================================
*/
static BOOLquadbox_is_valid(quadbox_t * qb)
{
return (qb -> _xmin < qb -> _xmax && qb -> _ymin < qb -> _ymax) ? TRUE:FALSE;
}

static double quadbox_width( const quadbox_t * qb)
{
return (qb -> _xmax - qb -> _xmin);
}

static double quadbox_height( const quadbox_t * qb)
{
return (qb -> _ymax - qb -> _ymin);
}

static void quadbox_init(quadbox_t * qb,
double xmin, double ymin, double xmax, double ymax)
{
qb
-> _xmin = xmin;qb -> _ymin = ymin;qb -> _xmax = xmax;qb -> _ymax = ymax;
assert(quadbox_is_valid(qb));
}

static void quadbox_inflate(quadbox_t * qb, double dx, double dy)
{
assert(dx
> 0 && dy > 0 );
qb
-> _xmin -= (dx / 2 );
qb
-> _xmax += (dx / 2 );
qb
-> _ymin -= (dy / 2 );
qb
-> _ymax += (dy / 2 );
}

/* splitsthequadrantsuchasbelow:
nw(0010)|ne(0001)
----------|----------
sw(0100)|se(1000)
*/
static void quadbox_split( const quadbox_t * qb,
quadbox_t
* ne,quadbox_t * nw,quadbox_t * se,quadbox_t * sw,
float overlap)
{
double dx = quadbox_width(qb) * ( 1.0 + overlap) / 2 ;
double dy = quadbox_height(qb) * ( 1.0 + overlap) / 2 ;

assert(overlap
>= QBOX_OVERLAP_MIN - 0.0001 );
assert(overlap
<= QBOX_OVERLAP_MAX + 0.0001 );

quadbox_init(ne,qb
-> _xmax - dx,qb -> _ymax - dy,qb -> _xmax,qb -> _ymax);
quadbox_init(nw,qb
-> _xmin,qb -> _ymax - dy,qb -> _xmin + dx,qb -> _ymax);
quadbox_init(sw,qb
-> _xmin,qb -> _ymin,qb -> _xmin + dx,qb -> _ymin + dy);
quadbox_init(se,qb
-> _xmax - dx,qb -> _ymin,qb -> _xmax,qb -> _ymin + dy);
}

/* returnsTRUEifthefirstisinsidethesenond */
static BOOLquadbox_is_inside( const quadbox_t * _first, const quadbox_t * _second)
{
return (_second -> _xmin < _first -> _xmin && _second -> _xmax > _first -> _xmax &&
_second
-> _ymin < _first -> _ymin && _second -> _ymax > _first -> _ymax) ? TRUE:FALSE;
}

/* returnsTRUEiftwoquad_boxisoverlapped */
static BOOLquadbox_is_overlapped( const quadbox_t * _first, const quadbox_t * _second)
{
return (_first -> _xmin > _second -> _xmax || _first -> _xmax < _second -> _xmin ||
_first
-> _ymin > _second -> _ymax || _first -> _ymax < _second -> _ymin) ? FALSE:TRUE;
}

static quadnode_t * quadnode_create( const quadbox_t * box)
{
quadnode_t
* node = (quadnode_t * )calloc( 1 , sizeof (quadnode_t));
if (node)
memcpy(
& (node -> _box),box, sizeof (quadbox_t));
return node;
}

static void quadnode_destroy(quadnode_t * node)
{
if (node -> _sub[NE] != 0 ){
quadnode_destroy(node
-> _sub[NE]);
quadnode_destroy(node
-> _sub[NW]);
quadnode_destroy(node
-> _sub[SE]);
quadnode_destroy(node
-> _sub[SW]);
}

if (node -> _lst)
list_destroy(node
-> _lst,NULL);

free(node);
}

static void quadnode_create_child(quadnode_t * node, float overlap, int depth)
{
quadbox_tne,nw,se,sw;

assert(node);
quadbox_split(
& (node -> _box), & ne, & nw, & se, & sw,overlap);

node
-> _sub[NE] = quadnode_create( & ne);
node
-> _sub[NW] = quadnode_create( & nw);
node
-> _sub[SW] = quadnode_create( & sw);
node
-> _sub[SE] = quadnode_create( & se);
}

static BOOLquadnode_has_child( const quadnode_t * node)
{
return (node -> _sub[NE] != 0 );
}

static BOOLquadnode_has_data( const quadnode_t * node)
{
return (node -> _lst && node -> _lst -> size > 0 ) ? TRUE:FALSE;
}

static void quadnode_add_data(quadnode_t * node, long node_key)
{
assert(node);
if ( ! node -> _lst)node -> _lst = list_create();
assert(node
-> _lst);
list_append_node(node
-> _lst,list_key_create(node_key));
}

/* insertsanodetoparentnodeoftree.returnspointertonode */
static quadnode_t * quadtree_insert_node(quadtree_t * tree,
quadnode_t
* parent,
long node_key,
quadbox_t
* node_box,
int * depth
)
{
if (quadbox_is_inside(node_box, & (parent -> _box)))
{
if ( ++ ( * depth) < tree -> _depth)
{
if ( ! quadnode_has_child(parent))
quadnode_create_child(parent,tree
-> _overlap,( * depth));

if (quadbox_is_inside(node_box, & (parent -> _sub[NE] -> _box)))
return quadtree_insert_node(tree,parent -> _sub[NE],node_key,node_box,depth);

if (quadbox_is_inside(node_box, & (parent -> _sub[NW] -> _box)))
return quadtree_insert_node(tree,parent -> _sub[NW],node_key,node_box,depth);

if (quadbox_is_inside(node_box, & (parent -> _sub[SW] -> _box)))
return quadtree_insert_node(tree,parent -> _sub[SW],node_key,node_box,depth);

if (quadbox_is_inside(node_box, & (parent -> _sub[SE] -> _box)))
return quadtree_insert_node(tree,parent -> _sub[SE],node_key,node_box,depth);
}

/* insertsintothisnodesinceitcanNOTbeincludedinanysubnodes */
quadnode_add_data(parent,node_key);
return parent;
}

return NULL;
}


/* searchedtreenodes */
static void quadtree_search_nodes(quadnode_t * current_node,
quadbox_t
* search_box,
list_t
* results_list
)
{
if (quadbox_is_overlapped( & (current_node -> _box),search_box))
{
if (quadnode_has_data(current_node))
list_append_node(results_list,list_node_create(current_node));

if (quadnode_has_child(current_node))
{
quadtree_search_nodes(current_node
-> _sub[NE],search_box,results_list);
quadtree_search_nodes(current_node
-> _sub[NW],search_box,results_list);
quadtree_search_nodes(current_node
-> _sub[SW],search_box,results_list);
quadtree_search_nodes(current_node
-> _sub[SE],search_box,results_list);
}
}
}


/* =============================================================================
PublicFunctions
=============================================================================
*/
quadtree_t
*
quadtree_create(quadbox_tbox,
int depth, /* 4~8 */
float overlap /* 0.02~0.4 */
)
{
quadtree_t
* qt = NULL;

assert(depth
>= QTREE_DEPTH_MIN - 0.0001 && depth <= QTREE_DEPTH_MAX + 0.0001 );
assert(overlap
>= QBOX_OVERLAP_MIN - 0.0001 && overlap <= QBOX_OVERLAP_MAX + 0.0001 );

qt
= (quadtree_t * )calloc( 1 , sizeof (quadtree_t));

if (qt)
{
qt
-> _depth = depth;
qt
-> _overlap = overlap;

quadbox_inflate(
& box,quadbox_width( & box) * overlap,quadbox_height( & box) * overlap);

qt
-> _root = quadnode_create( & box);
assert(qt
-> _root);
if ( ! qt -> _root)
{
free(qt);
qt
= NULL;
}
}

assert(qt);
return qt;
}

/* destroysaquadtree */
void
quadtree_destroy(INquadtree_t
* qtree)
{
assert(qtree
&& qtree -> _root);
quadnode_destroy(qtree
-> _root);
free(qtree);
}

/* insertsanodeintoquadtreeandreturnpointertonewnode */
quadnode_t
*
quadtree_insert(INquadtree_t
* qtree,
IN
long node_key,
INquadbox_t
* node_box
)
{
int depth = - 1 ;
return quadtree_insert_node(qtree,qtree -> _root,node_key,node_box, & depth);
}

/* searchesnodesinsidesearch_box */
void
quadtree_search(IN
const quadtree_t * qtree,
INquadbox_t
* search_box,
OUTlist_t
* results_list
)
{
quadtree_search_nodes(qtree
-> _root,search_box,results_list);
}

其中用到的文件(list.h,list.c,unistd.h)参考我的另一篇文章:

C语言实现一个简单的单向链表list

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值