K近邻算法(二)程序

本文介绍了一种基于最大方差特征选择的KD树构建方法,并实现了KD树的最近邻查询算法。通过具体代码示例详细展示了如何进行数据点的插入、树结构的构建过程以及查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


   #include<iostream>
#include<math.h>
#include <cmath>
#include<stack>
#define D  5  //维数
#define T  4  //类别
 
//#define mid  MAX/2
using namespace std;
int MAX =2000;
typedef struct Data
{
float data_x[D];
int   data_y[T];
}DATA;
DATA D_data[2000];
//定义KD树结构体
typedef  struct node
{
DATA  KD_data;
int   split;
struct node *ch_lift;
struct node *ch_right;
}KD_tree, *KD_str;
stack<KD_str> st_data;
//测试数据
typedef struct udata
{
float data_x[D];
float distanse;
DATA  PP_data;
}u_data;
//定义一个堆
//typedef struct sta
//{
// DATA  str;
//    int num;
//}STA_DATA;


int MAX_variance(DATA* D_da, int start, int end)
{
float sum = 0.0;
int att = 0;
float MAX_num = 0.0;
float* mean = new float[D];
float* variance = new float[D];
// if(start==end)
// {
// return start;
// }
// else
// {
for (int i = 0; i<D; i++)
{
for (int j = start; j <= end; j++)
{
sum = sum + D_da[j].data_x[i];
}
mean[i] = sum / (end - start + 1);
sum = 0.0;
}
for (int i = 0; i<D; i++)
{
for (int j = start; j <= end; j++)
{
sum = sum + pow(D_da[j].data_x[i] - mean[i], 2);
}
variance[i] = sum / (end - start + 1);
sum = 0.0;
}
for (int m = 0; m<D; m++)
{
if (MAX<variance[m])
{
MAX = variance[m];
att = m;
}
}
delete mean;
delete variance;
return att;
// }
}
void sort(int num1, int min_n1, int MAX_n1)
{
DATA temp;
int j;
// if(min_n1==MAX_n1)
// {
//  cout<<"";
//  }
//  else
//   {
for (int k = min_n1 + 1; k <= MAX_n1; k++)
{
if (D_data[k].data_x[num1]<D_data[k - 1].data_x[num1])
{
temp = D_data[k];
for (j = k - 1; D_data[j].data_x[num1]>temp.data_x[num1]; j--)
{
D_data[j + 1] = D_data[j];
}
D_data[j + 1] = temp;
}
}
//  }
}
bool create_kd_tree(int min_n, int MAX_n, KD_str p_tree)
{
//开辟空间


if (min_n>MAX_n)
{
p_tree = NULL;
return true;
}
else
{
if (min_n == MAX_n)
{
p_tree = new KD_tree;
p_tree->KD_data = D_data[min_n];
p_tree->split = -1;
}
else
{
int num = MAX_variance(D_data, min_n, MAX_n);
p_tree = new KD_tree;
if (!p_tree)
{
exit(1);
}
//直接插入排序
sort(num, min_n, MAX_n);
int mid = min_n + (MAX_n - min_n + 1) / 2;
p_tree->KD_data = D_data[mid];
p_tree->split = num;
//num=(num+1)%D;
create_kd_tree(min_n, mid - 1, p_tree->ch_lift);
create_kd_tree(mid + 1, MAX_n, p_tree->ch_right);
}
}
}
//距离函数
float distance(u_data dis_data, KD_str dis_tree)
{
//int dis_num=dis_tree->split;
float dis_num = 0;
for (int k = 0; k<D; k++)
{
dis_num = dis_num + pow(dis_data.data_x[k] - dis_tree->KD_data.data_x[k], 2);
}
dis_num = sqrt(dis_num);
return dis_num;


}
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////


DATA query_kd(u_data T_data, KD_str T_tree)
{
//STA_DATA  stae=NULL;
KD_str R_tree = T_tree;
int dot = R_tree->split;
//stae.num=dot;
//stae.str=R_tree->KD_data;
st_data.push(R_tree);
while (R_tree->ch_lift != NULL)
{
if (T_data.data_x[dot]<R_tree->KD_data.data_x[dot])
{
R_tree = R_tree->ch_lift;
//stae.str=R_tree->KD_data;
//dot=R_tree->split;
//stae.num=dot;
st_data.push(R_tree);
}
else
{
if (T_data.data_x[dot]>R_tree->KD_data.data_x[dot])
{
R_tree = R_tree->ch_right;
//stae.str=R_tree->KD_data;
//stae.num=dot;
//dot=R_tree->split;
st_data.push(R_tree);
}


}
}
//回溯
/*
STA_DATA run_data_1,run_data_2;
float sub_num;
run_data_1.str=st_data.pop();
T_data.distanse=distance(T_data,run_data_1.str);
run_data_2.str=st_data.push();
int flag=run_data_2.num;
sub_num=abs(run_data_1.str.data_x[flag]-run_data_2.str.data_x[flag]);
if (sub_num>T_data.distanse)
{              //继续往上回溯


}
else
{              //遍历另一个子树,


}
*/


KD_str run_data_1, run_data_2;
run_data_1 = st_data.top();
st_data.pop();
if (T_data.distanse<distance(T_data, run_data_1))
{
T_data.distanse = distance(T_data, run_data_1);
T_data.PP_data = run_data_1->KD_data;
}
int i_num;
while (st_data.empty())
{
run_data_1 = st_data.top();
st_data.pop();
i_num = run_data_1->split;
if (T_data.distanse<distance(T_data, run_data_1))
{
T_data.distanse = distance(T_data, run_data_1);
T_data.PP_data = run_data_1->KD_data;
}
if (abs(T_data.data_x[i_num] - run_data_1->KD_data.data_x[i_num])<T_data.distanse)
{
if (T_data.data_x[i_num]<run_data_1->KD_data.data_x[i_num])
{
run_data_2 = run_data_1->ch_right;
}
else
{
run_data_2 = run_data_1->ch_lift;
}
st_data.push(run_data_2);
}


}


}
void main()
{
//从TXT文件中读入数据


//数据处理把string转换float,数据的归一化


//求最大方差位
int digit_num;
KD_str Tree;
bool boolen;
int min = 0;
//digit_num=MAX_variance(D_data);
//创建kd树
boolen = create_kd_tree(min, MAX - 1, Tree);
if (boolen != true)
{
cout << "创建KD树失败!!!!" << endl;
exit(1);
}
//KD树的查询 先实现一个点
u_data TT;
TT.distanse = 10000;
query_kd(TT, Tree);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值