void rnnsearch(TREENODE *subroot, VECTOR *vp, int level, int n, VECTOR **bestn, NUMBER *min_nd, int *max_id, int *cnt){ NUMBER rootdist; /* the distance from the root */ int numdims; numdims = vp->len; if( subroot == NULL){ return; } /* empty tree */ rootdist = myvecdist2( vp, subroot->pvec); #ifdef DEBUG printf("rootdist %g nth mindist %g\n", rootdist, *min_nd); #endif if(rootdist < *min_nd && !subroot->fetched) { int i; bestn[*max_id] = subroot->pvec; *min_nd = myvecdist2(vp, bestn[0]); *max_id = 0; for(i = 1; i < n; i++) { if (myvecdist2(vp, bestn[i]) > *min_nd) { *min_nd = myvecdist2(vp, bestn[i]); *max_id = i; } } } /* check the subtrees - start from the most promising first */ if( (vp->vec)[level] > ((subroot->pvec)->vec)[level]){ /* the right subtree is more promising */ rnnsearch( subroot->right, vp, (level+1)% numdims, n, bestn, min_nd, max_id, cnt); /* now check the left subtree */ if( (*cnt) < n || (vp->vec)[level] <= ( ((subroot->pvec)->vec)[level] + (*min_nd) ) ){ /* only then is the left subtree promising */ /* notice that we use the UPDATED mindist */ rnnsearch( subroot->left, vp, (level+1)% numdims, n, bestn, min_nd, max_id, cnt); } }else{ /* the left subtree is more promising */ rnnsearch( subroot->left, vp, (level+1)% numdims, n, bestn, min_nd, max_id, cnt); /* now check the right subtree */ if( (*cnt) < n || ( (vp->vec)[level] + (*min_nd)) > ((subroot->pvec)->vec)[level] ){ rnnsearch( subroot->right, vp, (level+1)%numdims, n, bestn, min_nd, max_id, cnt); } } return; }
/* 'level' is the current level of the tree */ VECTOR *rnnsearch(TREENODE *subroot, VECTOR *vp, VECTOR *best, int level, VECTOR** bests, int count){ NUMBER mindist; /* the current best distance */ NUMBER rootdist; /* the distance from the root */ int numdims; numdims = vp->len; if(subroot == NULL){ return(best); } /* empty tree */ rootdist = myvecdist2( vp, subroot->pvec); mindist = myvecdist2( vp, best); #ifdef DEBUG printf("rootdist %g mindist %g\n", rootdist, mindist); #endif /* vecprint(subroot->pvec); */ save_knn(subroot->pvec, bests, count, vp); if(rootdist < mindist){ best = subroot->pvec; mindist = rootdist; } /* check the subtrees - start from the most promising first */ if( (vp->vec)[level] > ((subroot->pvec)->vec)[level]){ /* the right subtree is more promising */ best = rnnsearch( subroot->right, vp, best, (level+1)% numdims, bests, count); mindist = myvecdist2(vp, best); /* now check the left subtree */ if( (vp->vec)[level] <= ( ((subroot->pvec)->vec)[level] + mindist ) ){ /* only then is the left subtree promising */ /* notice that we use the UPDATED mindist */ best = rnnsearch( subroot->left, vp, best, (level+1)% numdims, bests, count); } } else { /* the left subtree is more promising */ best = rnnsearch( subroot->left, vp, best, (level+1)% numdims, bests, count); mindist = myvecdist2(vp, best); /* now check the right subtree */ if( ( (vp->vec)[level] + mindist) > ((subroot->pvec)->vec)[level] ){ best = rnnsearch( subroot->right, vp, best, (level+1)%numdims, bests, count); } } return(best); }
void getNNode(TREENODE *subroot, VECTOR *vp, int count, VECTOR **bestn, NUMBER *min_nd, int *max_id, int *cnt){ if ((*cnt) < count && subroot) { (*cnt)++; if ((*cnt) <= count ) { bestn[*cnt-1] = subroot->pvec; subroot->fetched = 1; if (*cnt == 1) { *max_id = 0; *min_nd = myvecdist2(vp, bestn[*cnt-1]); } else { if ((*min_nd) < myvecdist2(vp, bestn[*cnt-1])) { *max_id = *cnt-1; *min_nd = myvecdist2(vp, bestn[*cnt-1]); } } } getNNode(subroot->left, vp, count, bestn, min_nd, max_id, cnt); getNNode(subroot->right, vp, count, bestn, min_nd, max_id, cnt); } }
/* Added: runyunz - Fall 2013 */ void save_knn(VECTOR* best, VECTOR** bests, int count, VECTOR* vp){ int i, j; if(vp != NULL && bests != NULL) { if(bests[count-1] != NULL) { if(myvecdist2(vp, bests[count-1]) <= myvecdist2(vp, best)){ return; } } for(i=0; bests[i]!=NULL; i++) { if(myvecdist2(vp, best) < myvecdist2(vp, bests[i])){ for(j=count-1; j>i; j--){ bests[j] = bests[j-1]; } break; } } bests[i] = best; return; } }
void rknnsearch(TREENODE *subroot, VECTOR *vp, heap *hp, NUMBER radius, int level) { NUMBER rootdist; /* the distance from the root */ NUMBER max_dist_from_heap; int numdims; numdims = vp->len; if (subroot == NULL) { return; } rootdist = myvecdist2(vp, subroot->pvec); max_dist_from_heap = heap_max_dis(hp); if(max_dist_from_heap > rootdist && radius > rootdist) { heap_insert(hp, rootdist, subroot->pvec); } /* check the subtrees - start from the most promising first */ if( (vp->vec)[level] > ((subroot->pvec)->vec)[level]){ /* the right subtree is more promising */ rknnsearch(subroot->right, vp, hp, radius, (level+1)% numdims); max_dist_from_heap = heap_max_dis(hp); /* now check the left subtree */ if( (vp->vec)[level] <= ( ((subroot->pvec)->vec)[level] + max_dist_from_heap ) && (vp->vec)[level] <= (((subroot->pvec)->vec)[level] + radius)) { /* only then is the left subtree promising */ /* notice that we use the UPDATED mindist */ rknnsearch(subroot->left, vp, hp, radius, (level+1)% numdims); } }else{ /* the left subtree is more promising */ rknnsearch(subroot->left, vp, hp, radius, (level+1)% numdims); max_dist_from_heap = heap_max_dis(hp); /* now check the right subtree */ if( (vp->vec)[level] + max_dist_from_heap > (subroot->pvec->vec)[level] && (vp->vec)[level] + radius > ((subroot->pvec)->vec)[level]) { rknnsearch( subroot->right, vp, hp, radius, (level+1)%numdims); } } }
void nnsearch(TREENODE *subroot, VECTOR *vp, int count){ VECTOR **bestn = (VECTOR**)malloc(sizeof(VECTOR*) * count); NUMBER *bestn_d = (NUMBER*)malloc(sizeof(NUMBER) * count); NUMBER min_nd = HUGE; int max_id = 0; int cnt = 0; int i = 0; #ifdef DEBUG printf("nn tree search was called with \n"); vecprint(vp); #endif /* fetch count tree nodes first in case that there're less than count nodes */ getNNode(subroot, vp, count, bestn, &min_nd, &max_id, &cnt); rnnsearch(subroot, vp, 0, count, bestn, &min_nd, &max_id, &cnt); while(i < cnt) { bestn_d[i] = myvecdist2(vp, bestn[i]); i++; } if (cnt == 0) { printf("empty tree\n"); }else if(cnt < count) { printf("Only %d nodes found\n",cnt); } mergeSort(bestn, bestn_d, cnt); printf("nearest %d neighbors:\n",cnt); for(i = 0; i < cnt; i++){ vecprint(bestn[i]); printf("distance: %f\n", bestn_d[i]); } }