基于kd树的knn的实现原理可以参考文末的链接,都是一些好文章。

  这里参考了别人的代码。用c语言写的包括kd树的构建与查找k近邻的程序。

  code:

 #include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h> typedef struct{//数据维度
double x;
double y;
}data_struct; typedef struct kd_node{
data_struct split_data;//数据结点
int split;//分裂维
struct kd_node *left;//由位于该结点分割超面左子空间内所有数据点构成的kd-tree
struct kd_node *right;//由位于该结点分割超面右子空间内所有数据点构成的kd-tree
}kd_struct; //用于排序
int cmp1( const void *a , const void *b )
{
return (*(data_struct *)a).x > (*(data_struct *)b).x ? :-;
}
//用于排序
int cmp2( const void *a , const void *b )
{
return (*(data_struct *)a).y > (*(data_struct *)b).y ? :-;
}
//计算分裂维和分裂结点
void choose_split(data_struct data_set[],int size,int dimension,int *split,data_struct *split_data)
{
int i;
data_struct *data_temp;
data_temp=(data_struct *)malloc(size*sizeof(data_struct));
for(i=;i<size;i++)
data_temp[i]=data_set[i];
static int count=;//设为静态
*split=(count++)%dimension;//分裂维
if((*split)==) qsort(data_temp,size,sizeof(data_temp[]),cmp1);
else qsort(data_temp,size,sizeof(data_temp[]),cmp2);
*split_data=data_temp[(size-)/];//分裂结点排在中位
}
//判断两个数据点是否相等
int equal(data_struct a,data_struct b){
if(a.x==b.x && a.y==b.y) return ;
else return ;
}
//建立KD树
kd_struct *build_kdtree(data_struct data_set[],int size,int dimension,kd_struct *T)
{
if(size==) return NULL;//递归出口
else{
int sizeleft=,sizeright=;
int i,split;
data_struct split_data;
choose_split(data_set,size,dimension,&split,&split_data);
data_struct data_right[size];
data_struct data_left[size]; if (split==){//x维
for(i=;i<size;++i){
if(!equal(data_set[i],split_data) && data_set[i].x <= split_data.x){//比分裂结点小
data_left[sizeleft].x=data_set[i].x;
data_left[sizeleft].y=data_set[i].y;
sizeleft++;//位于分裂结点的左子空间的结点数
}
else if(!equal(data_set[i],split_data) && data_set[i].x > split_data.x){//比分裂结点大
data_right[sizeright].x=data_set[i].x;
data_right[sizeright].y=data_set[i].y;
sizeright++;//位于分裂结点的右子空间的结点数
}
}
}
else{//y维
for(i=;i<size;++i){
if(!equal(data_set[i],split_data) && data_set[i].y <= split_data.y){
data_left[sizeleft].x=data_set[i].x;
data_left[sizeleft].y=data_set[i].y;
sizeleft++;
}
else if (!equal(data_set[i],split_data) && data_set[i].y > split_data.y){
data_right[sizeright].x = data_set[i].x;
data_right[sizeright].y = data_set[i].y;
sizeright++;
}
}
}
T=(kd_struct *)malloc(sizeof(kd_struct));
T->split_data.x=split_data.x;
T->split_data.y=split_data.y;
T->split=split;
T->left=build_kdtree(data_left,sizeleft,dimension,T->left);//左子空间
T->right=build_kdtree(data_right,sizeright,dimension,T->right);//右子空间
return T;//返回指针
}
}
//计算欧氏距离
double compute_distance(data_struct a,data_struct b){
double tmp=pow(a.x-b.x,2.0)+pow(a.y-b.y,2.0);
return sqrt(tmp);
}
//搜索1近邻
void search_nearest(kd_struct *T,int size,data_struct test,data_struct *nearest_point,double *distance)
{
int path_size;//搜索路径内的指针数目
kd_struct *search_path[size];//搜索路径保存各结点的指针
kd_struct* psearch=T;
data_struct nearest;//最近邻的结点
double dist;//查询结点与最近邻结点的距离
search_path[]=psearch;//初始化搜索路径
path_size=;
while(psearch->left!=NULL || psearch->right!=NULL){
if (psearch->split==){
if(test.x <= psearch->split_data.x)//如果小于就进入左子树
psearch=psearch->left;
else
psearch=psearch->right;
}
else{
if(test.y <= psearch->split_data.y)//如果小于就进入右子树
psearch=psearch->left;
else
psearch=psearch->right;
}
search_path[path_size++]=psearch;//将经过的分裂结点保存在搜索路径中
}
//取出search_path最后一个元素,即叶子结点赋给nearest
nearest.x=search_path[path_size-]->split_data.x;
nearest.y=search_path[path_size-]->split_data.y;
path_size--;//search_path的指针数减一
dist=compute_distance(nearest,test);//计算与该叶子结点的距离作为初始距离 //回溯搜索路径
kd_struct* pback;
while(path_size!=){
pback=search_path[path_size-];//取出search_path最后一个结点赋给pback
path_size--;//search_path的指针数减一 if(pback->left==NULL && pback->right==NULL){//如果pback为叶子结点
if(dist>compute_distance(pback->split_data,test)){
nearest=pback->split_data;
dist=compute_distance(pback->split_data,test);
}
}
else{//如果pback为分裂结点
int s=pback->split;
if(s==){//x维
if(fabs(pback->split_data.x-test.x)<dist){//若以查询点为中心的圆(球或超球),半径为dist的圆与分割超平面相交,那么就要跳到另一边的子空间去搜索
if(dist>compute_distance(pback->split_data,test)){
nearest=pback->split_data;
dist=compute_distance(pback->split_data, test);
}
if(test.x<=pback->split_data.x)//若查询点位于pback的左子空间,那么就要跳到右子空间去搜索
psearch=pback->right;
else
psearch=pback->left;//若以查询点位于pback的右子空间,那么就要跳到左子空间去搜索
if(psearch!=NULL)
search_path[path_size++]=psearch;//psearch加入到search_path中
}
}
else {//y维
if(fabs(pback->split_data.y-test.y)<dist){//若以查询点为中心的圆(球或超球),半径为dist的圆与分割超平面相交,那么就要跳到另一边的子空间去搜索
if(dist>compute_distance(pback->split_data,test)){
nearest=pback->split_data;
dist=compute_distance(pback->split_data,test);
}
if(test.y<=pback->split_data.y)//若查询点位于pback的左子空间,那么就要跳到右子空间去搜索
psearch=pback->right;
else
psearch=pback->left;//若查询点位于pback的的右子空间,那么就要跳到左子空间去搜索
if(psearch!=NULL)
search_path[path_size++]=psearch;//psearch加入到search_path中
}
}
}
} (*nearest_point).x=nearest.x;//最近邻
(*nearest_point).y=nearest.y;
*distance=dist;//距离
} int main()
{
int n=;//数据个数
data_struct nearest_point;
double distance;
kd_struct *root=NULL;
data_struct data_set[]={{,},{,},{,},{,},{,},{,}};//数据集
data_struct test={7.1,2.1};//查询点
root=build_kdtree(data_set,n,,root); search_nearest(root,n,test,&nearest_point,&distance);
printf("nearest neighbor:(%.2f,%.2f)\ndistance:%.2f \n",nearest_point.x,nearest_point.y,distance);
return ;
}
/* x 5,4
/ \
y 2,3 7.2
\ / \
x 4,7 8.1 9.6
*/

参考:

  https://www.joinquant.com/post/2627?f=study&m=math

  https://www.joinquant.com/post/2843?f=study&m=math

  http://blog.csdn.net/zhl30041839/article/details/9277807

kd树和knn算法的c语言实现的更多相关文章

  1. knn算法的c语言实现

    最近研究KNN,找到了一些优秀的源码,贴出来,做个笔记吧. #include<stdio.h> #include<stdlib.h> #include<math.h> ...

  2. KNN算法的R语言实现

    近邻分类 简言之,就是将未标记的案例归类为与它们最近相似的.带有标记的案例所在的类. 应用领域: 1.计算机视觉:包含字符和面部识别等 2.推荐系统:推荐受众喜欢电影.美食和娱乐等 3.基因工程:识别 ...

  3. 深入浅出KNN算法(二) sklearn KNN实践

    姊妹篇: 深入浅出KNN算法(一) 原理介绍 上次介绍了KNN的基本原理,以及KNN的几个窍门,这次就来用sklearn实践一下KNN算法. 一.Skelarn KNN参数概述 要使用sklearnK ...

  4. 机器学习 KNN算法原理

    K近邻(K-nearst neighbors,KNN)是一种基本的机器学习算法,所谓k近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表.比如:判断一个人的人品,只需要观察 ...

  5. kd树的构建以及搜索

    构建算法 k-d树是一个二叉树,每个节点表示一个空间范围.表1给出的是k-d树每个节点中主要包含的数据结构. 表1 k-d树中每个节点的数据类型 域名 数据类型 描述 Node-data 数据矢量 数 ...

  6. KD树

    k-d树 在计算机科学里,k-d树( k-维树的缩写)是在k维欧几里德空间组织点的数据结构.k-d树可以使用在多种应用场合,如多维键值搜索(例:范围搜寻及最邻近搜索).k-d树是空间二分树(Binar ...

  7. 02-17 kd树

    目录 kd树 一.kd树学习目标 二.kd树引入 三.kd树详解 3.1 构造kd树 3.1.1 示例 3.2 kd树搜索 3.2.1 示例 四.kd树流程 4.1 输入 4.2 输出 4.3 流程 ...

  8. KNN算法与Kd树

    最近邻法和k-近邻法 下面图片中只有三种豆,有三个豆是未知的种类,如何判定他们的种类? 提供一种思路,即:未知的豆离哪种豆最近就认为未知豆和该豆是同一种类.由此,我们引出最近邻算法的定义:为了判定未知 ...

  9. 一看就懂的K近邻算法(KNN),K-D树,并实现手写数字识别!

    1. 什么是KNN 1.1 KNN的通俗解释 何谓K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,单从名字来猜想,可以简单粗暴的认为是:K个最近的邻居,当K=1 ...

随机推荐

  1. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  2. Failure to find xxx in xxx was cached in the local repository, resolution will not be reattempted until the update interval of nexus has elapsed or updates are forced @ xxx

    问题: 在linux服务器上使用maven编译war时报错: 16:41:35 [FATAL] Non-resolvable parent POM for ***: Failure to find * ...

  3. WCF学习之旅—基于Fault Contract 的异常处理(十八)

       WCF学习之旅—WCF中传统的异常处理(十六) WCF学习之旅—基于ServiceDebug的异常处理(十七) 三.基于Fault Contract 的异常处理 第二个示例是通过定制Servic ...

  4. GitHub实战系列~2.把本地项目提交到github中 2015-12-10

    GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...

  5. 【Win 10 应用开发】多媒体转码

    上次本来说好,今天咱们来讨论 socket 相关的话题,但,对于 socket ,老周还有一些问题没弄清楚,等弄清楚了,再和大伙伴们一起探讨.故,今天咱们扯一扯多媒体转码的事. 听起来挺复杂的,不过, ...

  6. 如何处理CSS3属性前缀

    今天闲来无聊,重新来说说CSS3前缀的问题.在春节前和@一丝姐姐说起Sass中有关于gradient的mixins.姐姐说: 为什么还要用mixin呢?为什么不使用Autoprefixer?使用Aut ...

  7. SVM分类与回归

    SVM(支撑向量机模型)是二(多)分类问题中经常使用的方法,思想比较简单,但是具体实现与求解细节对工程人员来说比较复杂,如需了解SVM的入门知识和中级进阶可点此下载.本文从应用的角度出发,使用Libs ...

  8. Beginners Guide To Web Development

    Web Development Front End Development Back End Development

  9. SQL语句优化

    (1)      选择最有效率的表名顺序 ( 只在基于规则的优化器中有效 ) : ORACLE 的解析器按照从右到左的顺序处理 FROM 子句中的表名, FROM 子句中写在最后的表 ( 基础表dri ...

  10. Memcache缓存系统构建一

    在如今这个高效率的社会中,怎样将这个高效率应用到自己的程序中,是一个值得追寻和值得探讨的问题.因为这个memcache能够很好的提高检索速度,提升用户体验,而且重要的是减少数据库的访问.这就大大的提高 ...