KNN演算法---求前K個數據。
阿新 • • 發佈:2019-01-04
簡介
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即可。