简介
K Nearest Neighbor算法又叫KNN算法,K最近邻算法。K表示距离自己最近的k个数据样本。
个人觉得重点在距离如何表示,如何计算,是简单的用距离公式,还是用复杂的加权计算。最后都会输出
一个距离值。剩下的问题就可以抽象成一个求前K个数据。
代码
#include <vector>
#include <iostream>
using namespace std;
void adjust_heap(vector<int> & vec, int length, int i);
void gen_max_heap(vector<int> & vec);
void get_kmax_value(vector<int> &vec, vector<int> &kvec, int k);
int main()
{
vector<int> vec = { 0, 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 };//第一位不用
gen_max_heap(vec);
vector<int> kvec;
get_kmax_value(vec,kvec, 5);
for (auto x : kvec)
cout << x << endl;
cin.get();
return 0;
}
void adjust_heap(vector<int> & vec, int length, int root)
{
int left = 2 * i;
int right = 2 * i + 1;
int largest = root;
while (left < length || right < length)
{
if (left < length && vec[left] > vec[largest])
largest = left;
if (right < length && vec[right] > vec[largest])
largest = right;
if (i != largest)//继续调整被影响的子树
{
swap(vec[largest], vec[i]);
root = largest;
left = 2 * root;
right = 2 * root + 1;
}
else
{
break;
}
}
}
void gen_max_heap(vector<int> & vec)
{
int length = vec.size();
for (auto root = (vec.size() - 1) / 2; root != 0; root--)
{
adjust_heap(vec, length, root);
}
}
void get_kmax_value(vector<int> &vec, vector<int> &kvec, int k)
{
int length = vec.size();
for (int i = 0; i != k; ++i)
{
kvec.push_back(vec[1]);
swap(vec[1], vec[length - 1 - i]);
adjust_heap(vec, length - 1 - i, 1);
}
}
//请使用支持c++11的编译器编译
分析
- 求前k个数据,常用的方法利用max_heap(大根堆)。
简介大根堆,一棵完全二叉树,每个节点值都大于其子节点的值。 - 本人代码写的比较渣,在选择数据结构的时候选择了vector,在用的时候下标这个点很头疼。
父子节点的下标问题:
2.1 vec[0]元素不用。下标从1开始到n,子节点n,父节点[n/2]对应实现。
2.2 下标与循环变量的选择。 - 核心在这个adjust_heap的操作
如何构建大根堆,首先从最小的子树开始,本来应该是叶子节点。但是一个节点也没必要比较。
那就从一个root和一层孩子的节点子树开始。这样的子树很简单就可以调整成root值大于孩子节点。
关键是从3层的子树结构开始。由root和两个分别已经调整后的2层子树组成的子树。若root和两个孩子
有所调整,那将影响调整的孩子的子树,那么将继续调整被影响的子树。无需调整的话,由于两个孩子也是已经调整好的,所以整个子树也不需要调整,break即可。