kD-tree 的C语言实现 带有史上最全的注释和解释

来源:互联网 发布:华为路由器 端口转发 编辑:程序博客网 时间:2024/06/07 10:19
kdtree的原理就是基于二叉树的形式,将高维空间用超矩形进行划分.其主要用途是用来求解高维空间中最近邻的值.

 

 

下面是kdtree.h文件,是kdtree数据结构的头文件

#ifndef _KDTREE_H_#define _KDTREE_H_#ifdef __cplusplusextern "C" {#endifstruct kdtree;struct kdres;/* create a kd-tree for "k"-dimensional data */struct kdtree *kd_create(int k);/* free the struct kdtree */void kd_free(struct kdtree *tree);/* remove all the elements from the tree */void kd_clear(struct kdtree *tree);/* if called with non-null 2nd argument, the function provided * will be called on data pointers (see kd_insert) when nodes * are to be removed from the tree. */void kd_data_destructor(struct kdtree *tree, void (*destr)(void*));/* insert a node, specifying its position, and optional data */int kd_insert(struct kdtree *tree, const double *pos, void *data);int kd_insertf(struct kdtree *tree, const float *pos, void *data);int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data);int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data);/* Find the nearest node from a given point. * * This function returns a pointer to a result set with at most one element. */struct kdres *kd_nearest(struct kdtree *tree, const double *pos);struct kdres *kd_nearestf(struct kdtree *tree, const float *pos);struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z);struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z);/* Find the N nearest nodes from a given point. * * This function returns a pointer to a result set, with at most N elements, * which can be manipulated with the kd_res_* functions. * The returned pointer can be null as an indication of an error. Otherwise * a valid result set is always returned which may contain 0 or more elements. * The result set must be deallocated with kd_res_free after use. *//*struct kdres *kd_nearest_n(struct kdtree *tree, const double *pos, int num);struct kdres *kd_nearest_nf(struct kdtree *tree, const float *pos, int num);struct kdres *kd_nearest_n3(struct kdtree *tree, double x, double y, double z);struct kdres *kd_nearest_n3f(struct kdtree *tree, float x, float y, float z);*//* Find any nearest nodes from a given point within a range. * * This function returns a pointer to a result set, which can be manipulated * by the kd_res_* functions. * The returned pointer can be null as an indication of an error. Otherwise * a valid result set is always returned which may contain 0 or more elements. * The result set must be deallocated with kd_res_free after use. */struct kdres *kd_nearest_range(struct kdtree *tree, const double *pos, double range);struct kdres *kd_nearest_rangef(struct kdtree *tree, const float *pos, float range);struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range);struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range);/* frees a result set returned by kd_nearest_range() */void kd_res_free(struct kdres *set);/* returns the size of the result set (in elements) */int kd_res_size(struct kdres *set);/* rewinds the result set iterator */void kd_res_rewind(struct kdres *set);/* returns non-zero if the set iterator reached the end after the last element */int kd_res_end(struct kdres *set);/* advances the result set iterator, returns non-zero on success, zero if * there are no more elements in the result set. */int kd_res_next(struct kdres *set);/* returns the data pointer (can be null) of the current result set item * and optionally sets its position to the pointers(s) if not null. */void *kd_res_item(struct kdres *set, double *pos);void *kd_res_itemf(struct kdres *set, float *pos);void *kd_res_item3(struct kdres *set, double *x, double *y, double *z);void *kd_res_item3f(struct kdres *set, float *x, float *y, float *z);/* equivalent to kd_res_item(set, 0) */void *kd_res_item_data(struct kdres *set);#ifdef __cplusplus}#endif#endif/* _KDTREE_H_ */


下面是kdtree.c 文件,上面有我自己精心整理的详细的汉语注释,这个版本的kdtree可直接拿来用

//kd_tree.h  kd_tree的头文件#include "stdafx.h"//头文件#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#include "kd_tree.h"#if defined(WIN32) || defined(__WIN32__)#include <malloc.h>#endif#ifdef USE_LIST_NODE_ALLOCATOR#ifndef NO_PTHREADS#include <pthread.h>#else#ifndef I_WANT_THREAD_BUGS#error "You are compiling with the fast list node allocator, with pthreads disabled! This WILL break if used from multiple threads."#endif/* I want thread bugs */#endif/* pthread support */#endif/* use list node allocator *///超平面的结构体//包括一个属性的维数和每维坐标的最大和最小值构成的数组struct kdhyperrect {int dim;double *min, *max;              /* minimum/maximum coords */};//节点的结构体,也就是事例的结构体struct kdnode {double *pos;int dir;void *data;struct kdnode *left, *right;/* negative/positive side */};//返回结果节点, 包括树的节点,距离值, 是一个单链表的形式struct res_node {struct kdnode *item;double dist_sq;struct res_node *next;};//树有几个属性,一是维数,一是树根节点,一是超平面,一是销毁data的函数struct kdtree {int dim;struct kdnode *root;struct kdhyperrect *rect;void (*destr)(void*);};//kdtree的返回结果,包括kdtree,这是一个双链表的形式struct kdres {struct kdtree *tree;struct res_node *rlist, *riter;  //双链表?int size;};//计算平方的宏定义,相当于函数#define SQ(x)((x) * (x))static void clear_rec(struct kdnode *node, void (*destr)(void*));static int insert_rec(struct kdnode **node, const double *pos, void *data, int dir, int dim);static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq);static void clear_results(struct kdres *set);static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max);static void hyperrect_free(struct kdhyperrect *rect);static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect);static void hyperrect_extend(struct kdhyperrect *rect, const double *pos);static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos);#ifdef USE_LIST_NODE_ALLOCATORstatic struct res_node *alloc_resnode(void);static void free_resnode(struct res_node*);#else#define alloc_resnode()malloc(sizeof(struct res_node))#define free_resnode(n)free(n)#endif//创建一个kdtreestruct kdtree *kd_create(int k){struct kdtree *tree;if(!(tree = (kdtree*)malloc(sizeof *tree))) {return 0;}tree->dim = k;tree->root = 0;tree->destr = 0;tree->rect = 0;return tree;}//释放掉kdtreevoid kd_free(struct kdtree *tree){if(tree) {kd_clear(tree);free(tree);}}//清除掉超平面,是按节点递归地进行的static void clear_rec(struct kdnode *node, void (*destr)(void*)){if(!node) return;   //一个节点对应一个超平面//递归函数,递归地清除掉二叉树左分支的超平面和二叉树右分支的超平面clear_rec(node->left, destr);clear_rec(node->right, destr);//如果data清楚函数不为空,就释放掉dataif(destr) {destr(node->data);}//释放节点的坐标数组free(node->pos);//释放节点free(node);}//kdtree清除void kd_clear(struct kdtree *tree){//清除树中每个节点的超平面,释放树中的各个节点clear_rec(tree->root, tree->destr);tree->root = 0;//如果树的超平面指针不为空,对其进行释放if (tree->rect) {hyperrect_free(tree->rect);tree->rect = 0;}}//数据销毁,用一个外来的函数来进行data的销毁void kd_data_destructor(struct kdtree *tree, void (*destr)(void*)){//用外来的函数来执行kdtree的销毁函数tree->destr = destr;}//在一个树节点位置处插入超矩形static int insert_rec(struct kdnode **nptr, const double *pos, void *data, int dir, int dim){int new_dir;struct kdnode *node;//如果这个节点是不存在的if(!*nptr) {//分配一个结点if(!(node = (kdnode *)malloc(sizeof *node))) {return -1;}if(!(node->pos = (double*)malloc(dim * sizeof *node->pos))) {free(node);return -1;}memcpy(node->pos, pos, dim * sizeof *node->pos);node->data = data;node->dir = dir;node->left = node->right = 0;*nptr = node;return 0;}node = *nptr;new_dir = (node->dir + 1) % dim;if(pos[node->dir] < node->pos[node->dir]) {return insert_rec(&(*nptr)->left, pos, data, new_dir, dim);}return insert_rec(&(*nptr)->right, pos, data, new_dir, dim);}//节点插入操作//参数为:要进行插入操作的kdtree,要插入的节点坐标,要插入的节点的数据int kd_insert(struct kdtree *tree, const double *pos, void *data){//插入超矩形if (insert_rec(&tree->root, pos, data, 0, tree->dim)) {return -1;}//如果树还没有超矩形,就创建一个超矩形//如果已经有了超矩形,就扩展原有的超矩形if (tree->rect == 0) {tree->rect = hyperrect_create(tree->dim, pos, pos);} else {hyperrect_extend(tree->rect, pos);}return 0;}//插入float型坐标的节点//参数为:要进行插入操作的kdtree,要插入的节点坐标,要插入的节点的数据//将float型的坐标赋值给double型的缓冲区,经过这个类型转化后进行插入//本质上是一种类型转化int kd_insertf(struct kdtree *tree, const float *pos, void *data){static double sbuf[16];double *bptr, *buf = 0;int res, dim = tree->dim;//如果kdtree的维数大于16, 分配dim维double类型的数组if(dim > 16) {#ifndef NO_ALLOCAif(dim <= 256)bptr = buf = (double*)alloca(dim * sizeof *bptr);else#endifif(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {return -1;}} //如果kdtree的维数小于16, 直接将指针指向已分配的内存else {bptr = buf = sbuf;}//将要插入点的位置坐标赋值给分配的数组while(dim-- > 0) {*bptr++ = *pos++;}//调用节点插入函数kd_insertres = kd_insert(tree, buf, data);#ifndef NO_ALLOCAif(tree->dim > 256)#elseif(tree->dim > 16)#endif        //释放缓存free(buf);return res;}//给出三维坐标值的三维kdtree插入int kd_insert3(struct kdtree *tree, double x, double y, double z, void *data){double buf[3];buf[0] = x;buf[1] = y;buf[2] = z;return kd_insert(tree, buf, data);}//给出三维float型坐标值的三维kdtree插入int kd_insert3f(struct kdtree *tree, float x, float y, float z, void *data){double buf[3];buf[0] = x;buf[1] = y;buf[2] = z;return kd_insert(tree, buf, data);}//找到最近邻的点//参数为:树节点指针, 位置坐标, 阈值, 返回结果的节点, bool型排序,维度static int find_nearest(struct kdnode *node, const double *pos, double range, struct res_node *list, int ordered, int dim){double dist_sq, dx;int i, ret, added_res = 0;if(!node) return 0;  //注意这个地方,当节点为空的时候,表明已经查找到最终的叶子结点,返回值为零dist_sq = 0;//计算两个节点间的平方和for(i=0; i<dim; i++) {dist_sq += SQ(node->pos[i] - pos[i]);}//如果距离在阈值范围内,就将其插入到返回结果链表中if(dist_sq <= SQ(range)) {if(rlist_insert(list, node, ordered ? dist_sq : -1.0) == -1) {return -1;}added_res = 1;}//在这个节点的划分方向上,求两者之间的差值dx = pos[node->dir] - node->pos[node->dir];//根据这个差值的符号, 选择进行递归查找的分支方向ret = find_nearest(dx <= 0.0 ? node->left : node->right, pos, range, list, ordered, dim);//如果返回的值大于等于零,表明在这个分支中有满足条件的节点,则返回结果的个数进行累加,并在节点的另一个方向进行查找最近的节点if(ret >= 0 && fabs(dx) < range) {added_res += ret;ret = find_nearest(dx <= 0.0 ? node->right : node->left, pos, range, list, ordered, dim);}if(ret == -1) {return -1;}added_res += ret;return added_res;}//找到最近邻的n个节点#if 0static int find_nearest_n(struct kdnode *node, const double *pos, double range, int num, struct rheap *heap, int dim){double dist_sq, dx;int i, ret, added_res = 0;if(!node) return 0;/* if the photon is close enough, add it to the result heap *///如果足够近就将其加入到结果堆中dist_sq = 0;//计算两者间的欧式距离for(i=0; i<dim; i++) {dist_sq += SQ(node->pos[i] - pos[i]);}//如果计算所得距离小于阈值if(dist_sq <= range_sq) {//如果堆的大小大于num,也就是大于总的要找的节点数if(heap->size >= num){/* get furthest element *///得到最远的节点struct res_node *maxelem = rheap_get_max(heap);/* and check if the new one is closer than that *///测试这个节点是不是比最远的节点要近if(maxelem->dist_sq > dist_sq) {//如果是的话,就移除最远的节点rheap_remove_max(heap);//并将此节点插入堆中if(rheap_insert(heap, node, dist_sq) == -1) {return -1;}added_res = 1;range_sq = dist_sq;}} //如果堆的大小小于num,直接将此节点插入堆中else {if(rheap_insert(heap, node, dist_sq) == -1) {return =1;}added_res = 1;}}/* find signed distance from the splitting plane */dx = pos[node->dir] - node->pos[node->dir];ret = find_nearest_n(dx <= 0.0 ? node->left : node->right, pos, range, num, heap, dim);if(ret >= 0 && fabs(dx) < range) {added_res += ret;ret = find_nearest_n(dx <= 0.0 ? node->right : node->left, pos, range, num, heap, dim);}}#endifstatic void kd_nearest_i(struct kdnode *node, const double *pos, struct kdnode **result, double *result_dist_sq, struct kdhyperrect* rect){int dir = node->dir;int i;double dummy, dist_sq;struct kdnode *nearer_subtree, *farther_subtree;double *nearer_hyperrect_coord, *farther_hyperrect_coord;/* Decide whether to go left or right in the tree *///在二叉树中,决定向左走还是向右走dummy = pos[dir] - node->pos[dir];if (dummy <= 0) {nearer_subtree = node->left;farther_subtree = node->right;nearer_hyperrect_coord = rect->max + dir;farther_hyperrect_coord = rect->min + dir;} else {nearer_subtree = node->right;farther_subtree = node->left;nearer_hyperrect_coord = rect->min + dir;farther_hyperrect_coord = rect->max + dir;}if (nearer_subtree) {/* Slice the hyperrect to get the hyperrect of the nearer subtree */dummy = *nearer_hyperrect_coord;*nearer_hyperrect_coord = node->pos[dir];/* Recurse down into nearer subtree */kd_nearest_i(nearer_subtree, pos, result, result_dist_sq, rect);/* Undo the slice */*nearer_hyperrect_coord = dummy;}/* Check the distance of the point at the current node, compare it * with our best so far */dist_sq = 0;for(i=0; i < rect->dim; i++) {dist_sq += SQ(node->pos[i] - pos[i]);}if (dist_sq < *result_dist_sq) {*result = node;*result_dist_sq = dist_sq;}if (farther_subtree) {/* Get the hyperrect of the farther subtree */dummy = *farther_hyperrect_coord;*farther_hyperrect_coord = node->pos[dir];/* Check if we have to recurse down by calculating the closest * point of the hyperrect and see if it's closer than our * minimum distance in result_dist_sq. */if (hyperrect_dist_sq(rect, pos) < *result_dist_sq) {/* Recurse down into farther subtree */kd_nearest_i(farther_subtree, pos, result, result_dist_sq, rect);}/* Undo the slice on the hyperrect */*farther_hyperrect_coord = dummy;}}//求kdtree中与点pos最近邻的值struct kdres *kd_nearest(struct kdtree *kd, const double *pos){struct kdhyperrect *rect;struct kdnode *result;struct kdres *rset;double dist_sq;int i;//如果kd不存在,或者其超平面不存在的话,则就不会有结果if (!kd) return 0;if (!kd->rect) return 0;/* Allocate result set *///为返回结果集合分配空间if(!(rset = (kdres*)malloc(sizeof *rset))) {return 0;}if(!(rset->rlist = (res_node*)alloc_resnode())) {free(rset);return 0;}rset->rlist->next = 0;rset->tree = kd;/* Duplicate the bounding hyperrectangle, we will work on the copy *///复制边界超平面if (!(rect = hyperrect_duplicate(kd->rect))) {kd_res_free(rset);return 0;}/* Our first guesstimate is the root node */result = kd->root;dist_sq = 0;for (i = 0; i < kd->dim; i++)dist_sq += SQ(result->pos[i] - pos[i]);/* Search for the nearest neighbour recursively *///递归地查找最近邻的邻居kd_nearest_i(kd->root, pos, &result, &dist_sq, rect);/* Free the copy of the hyperrect *///释放超矩形hyperrect_free(rect);/* Store the result *///存储结果if (result) {if (rlist_insert(rset->rlist, result, -1.0) == -1) {kd_res_free(rset);return 0;}rset->size = 1;kd_res_rewind(rset);return rset;} else {kd_res_free(rset);return 0;}}//kd_nearest的float特例struct kdres *kd_nearestf(struct kdtree *tree, const float *pos){static double sbuf[16];double *bptr, *buf = 0;int dim = tree->dim;struct kdres *res;if(dim > 16) {#ifndef NO_ALLOCAif(dim <= 256)bptr = buf = (double*)alloca(dim * sizeof *bptr);else#endifif(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {return 0;}} else {bptr = buf = sbuf;}while(dim-- > 0) {*bptr++ = *pos++;}res = kd_nearest(tree, buf);#ifndef NO_ALLOCAif(tree->dim > 256)#elseif(tree->dim > 16)#endiffree(buf);return res;}//kd_nearest的三坐标特例struct kdres *kd_nearest3(struct kdtree *tree, double x, double y, double z){double pos[3];pos[0] = x;pos[1] = y;pos[2] = z;return kd_nearest(tree, pos);}//kd_nearest的三坐标float特例struct kdres *kd_nearest3f(struct kdtree *tree, float x, float y, float z){double pos[3];pos[0] = x;pos[1] = y;pos[2] = z;return kd_nearest(tree, pos);}/* ---- nearest N search ---- *//*static kdres *kd_nearest_n(struct kdtree *kd, const double *pos, int num){int ret;struct kdres *rset;if(!(rset = malloc(sizeof *rset))) {return 0;}if(!(rset->rlist = alloc_resnode())) {free(rset);return 0;}rset->rlist->next = 0;rset->tree = kd;if((ret = find_nearest_n(kd->root, pos, range, num, rset->rlist, kd->dim)) == -1) {kd_res_free(rset);return 0;}rset->size = ret;kd_res_rewind(rset);return rset;}*///找到满足距离小于range值的节点struct kdres *kd_nearest_range(struct kdtree *kd, const double *pos, double range){int ret;struct kdres *rset;if(!(rset = (kdres*)malloc(sizeof *rset))) {return 0;}if(!(rset->rlist = (res_node*)alloc_resnode())) {free(rset);return 0;}rset->rlist->next = 0;rset->tree = kd;if((ret = find_nearest(kd->root, pos, range, rset->rlist, 0, kd->dim)) == -1) {kd_res_free(rset);return 0;}rset->size = ret;kd_res_rewind(rset);return rset;}//kd_nearest_range的float特例struct kdres *kd_nearest_rangef(struct kdtree *kd, const float *pos, float range){static double sbuf[16];double *bptr, *buf = 0;int dim = kd->dim;struct kdres *res;if(dim > 16) {#ifndef NO_ALLOCAif(dim <= 256)bptr = buf = (double*)alloca(dim * sizeof *bptr);else#endifif(!(bptr = buf = (double*)malloc(dim * sizeof *bptr))) {return 0;}} else {bptr = buf = sbuf;}while(dim-- > 0) {*bptr++ = *pos++;}res = kd_nearest_range(kd, buf, range);#ifndef NO_ALLOCAif(kd->dim > 256)#elseif(kd->dim > 16)#endiffree(buf);return res;}//kd_nearest_range的三坐标特例struct kdres *kd_nearest_range3(struct kdtree *tree, double x, double y, double z, double range){double buf[3];buf[0] = x;buf[1] = y;buf[2] = z;return kd_nearest_range(tree, buf, range);}//kd_nearest_range的三坐标float特例struct kdres *kd_nearest_range3f(struct kdtree *tree, float x, float y, float z, float range){double buf[3];buf[0] = x;buf[1] = y;buf[2] = z;return kd_nearest_range(tree, buf, range);}//返回结果的释放void kd_res_free(struct kdres *rset){clear_results(rset);free_resnode(rset->rlist);free(rset);}//获取返回结果集合的大小int kd_res_size(struct kdres *set){return (set->size);}//再次回到这个节点本身的位置void kd_res_rewind(struct kdres *rset){rset->riter = rset->rlist->next;}//找到返回结果中的最终节点int kd_res_end(struct kdres *rset){return rset->riter == 0;}//返回结果列表中的下一个节点int kd_res_next(struct kdres *rset){rset->riter = rset->riter->next;return rset->riter != 0;}//将返回结果的节点的坐标和data抽取出来void *kd_res_item(struct kdres *rset, double *pos){if(rset->riter) {if(pos) {memcpy(pos, rset->riter->item->pos, rset->tree->dim * sizeof *pos);}return rset->riter->item->data;}return 0;}//将返回结果的节点的坐标和data抽取出来,坐标为float型的值void *kd_res_itemf(struct kdres *rset, float *pos){if(rset->riter) {if(pos) {int i;for(i=0; i<rset->tree->dim; i++) {pos[i] = rset->riter->item->pos[i];}}return rset->riter->item->data;}return 0;}//将返回结果的节点的坐标和data抽取出来,坐标具体形式给出void *kd_res_item3(struct kdres *rset, double *x, double *y, double *z){if(rset->riter) {if(*x) *x = rset->riter->item->pos[0];if(*y) *y = rset->riter->item->pos[1];if(*z) *z = rset->riter->item->pos[2];}return 0;}//将返回结果的节点的坐标和data抽取出来,坐标为float型的值,坐标具体形式给出void *kd_res_item3f(struct kdres *rset, float *x, float *y, float *z){if(rset->riter) {if(*x) *x = rset->riter->item->pos[0];if(*y) *y = rset->riter->item->pos[1];if(*z) *z = rset->riter->item->pos[2];}return 0;}//获取data数据void *kd_res_item_data(struct kdres *set){return kd_res_item(set, 0);}/* ---- hyperrectangle helpers ---- *///创建超平面,包括三个参数:维度,每维的最小值和最大值数组static struct kdhyperrect* hyperrect_create(int dim, const double *min, const double *max){size_t size = dim * sizeof(double);struct kdhyperrect* rect = 0;if (!(rect = (kdhyperrect*)malloc(sizeof(struct kdhyperrect)))) {return 0;}rect->dim = dim;if (!(rect->min = (double*)malloc(size))) {free(rect);return 0;}if (!(rect->max = (double*)malloc(size))) {free(rect->min);free(rect);return 0;}memcpy(rect->min, min, size);memcpy(rect->max, max, size);return rect;}//释放超平面结构体static void hyperrect_free(struct kdhyperrect *rect){free(rect->min);free(rect->max);free(rect);}//赋值超平面结构体static struct kdhyperrect* hyperrect_duplicate(const struct kdhyperrect *rect){return hyperrect_create(rect->dim, rect->min, rect->max);}//更新超平面结构体最大\最小值数组static void hyperrect_extend(struct kdhyperrect *rect, const double *pos){int i;for (i=0; i < rect->dim; i++) {if (pos[i] < rect->min[i]) {rect->min[i] = pos[i];}if (pos[i] > rect->max[i]) {rect->max[i] = pos[i];}}}//计算固定坐标点与超平面之间的距离static double hyperrect_dist_sq(struct kdhyperrect *rect, const double *pos){int i;double result = 0;for (i=0; i < rect->dim; i++) {if (pos[i] < rect->min[i]) {result += SQ(rect->min[i] - pos[i]);} else if (pos[i] > rect->max[i]) {result += SQ(rect->max[i] - pos[i]);}}return result;}/* ---- static helpers ---- */#ifdef USE_LIST_NODE_ALLOCATOR/* special list node allocators. */static struct res_node *free_nodes;#ifndef NO_PTHREADSstatic pthread_mutex_t alloc_mutex = PTHREAD_MUTEX_INITIALIZER;#endif//创建返回结果节点static struct res_node *alloc_resnode(void){struct res_node *node;#ifndef NO_PTHREADSpthread_mutex_lock(&alloc_mutex);#endifif(!free_nodes) {node = malloc(sizeof *node);} else {node = free_nodes;free_nodes = free_nodes->next;node->next = 0;}#ifndef NO_PTHREADSpthread_mutex_unlock(&alloc_mutex);#endifreturn node;}//释放返回结果节点static void free_resnode(struct res_node *node){#ifndef NO_PTHREADSpthread_mutex_lock(&alloc_mutex);#endifnode->next = free_nodes;free_nodes = node;#ifndef NO_PTHREADSpthread_mutex_unlock(&alloc_mutex);#endif}#endif/* list node allocator or not *//* inserts the item. if dist_sq is >= 0, then do an ordered insert *//* TODO make the ordering code use heapsort *///函数参数: 返回结果节点指针,树节点指针,距离函数//将一个结果节点插入到返回结果的列表中static int rlist_insert(struct res_node *list, struct kdnode *item, double dist_sq){struct res_node *rnode;//创建一个返回结果的节点if(!(rnode = (res_node*)alloc_resnode())) {return -1;}rnode->item = item;           //对应的树节点rnode->dist_sq = dist_sq;     //对应的距离值//当距离大于零的时候if(dist_sq >= 0.0) {while(list->next && list->next->dist_sq < dist_sq) {list = list->next;}}rnode->next = list->next;list->next = rnode;return 0;}//清除返回结果的集合//本质上是个双链表中单链表的清理static void clear_results(struct kdres *rset){struct res_node *tmp, *node = rset->rlist->next;while(node) {tmp = node;node = node->next;free_resnode(tmp);}rset->rlist->next = 0;}


 

原创粉丝点击