1. 程式人生 > >KNN演算法---求前K個數據。

KNN演算法---求前K個數據。

簡介

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的編譯器編譯

分析

  1. 求前k個數據,常用的方法利用max_heap(大根堆)。
    簡介大根堆,一棵完全二叉樹,每個節點值都大於其子節點的值。
  2. 本人程式碼寫的比較渣,在選擇資料結構的時候選擇了vector,在用的時候下標這個點很頭疼。
    父子節點的下標問題:
    2.1 vec[0]元素不用。下標從1開始到n,子節點n,父節點[n/2]對應實現。
    2.2 下標與迴圈變數的選擇。
  3. 核心在這個adjust_heap的操作
    如何構建大根堆,首先從最小的子樹開始,本來應該是葉子節點。但是一個節點也沒必要比較。
    那就從一個root和一層孩子的節點子樹開始。這樣的子樹很簡單就可以調整成root值大於孩子節點。
    關鍵是從3層的子樹結構開始。由root和兩個分別已經調整後的2層子樹組成的子樹。若root和兩個孩子
    有所調整,那將影響調整的孩子的子樹,那麼將繼續調整被影響的子樹。無需調整的話,由於兩個孩子也是已經調整好的,所以整個子樹也不需要調整,break即可。