K-Nearest Neighbors (KNN) 是最經典的監督式分類演算法。核心思想:「靠近朱者赤,靠近墨者黑」——在特徵空間中,若一個待分類樣本的 K 個最近鄰居多數屬於某類別,則該樣本亦屬於該類別。
float **data:動態二維陣列儲存訓練資料 [N][D]int *in_cluster:記錄每筆資料所屬類別float **karray:[2][K] 暫存「距離、標籤」對,用於維護前 K 小距離// 動態配置二維陣列(連續記憶體)
float **createarray(int n, int m) {
float **arr = malloc(n * sizeof(float *));
arr[0] = malloc(n * m * sizeof(float));
for (int i = 1; i < n; ++i) arr[i] = arr[i-1] + m;
return arr;
}
// 歐氏距離
float distance(float *a, float *b, int dim) {
float sum = 0;
for (int i = 0; i < dim; ++i) sum += (a[i]-b[i])*(a[i]-b[i]);
return sqrtf(sum);
}
// 維護前 K 小距離(插入排序優化)
void update_knn(float **karr, float dist, float label, int K) {
for (int j = 0; j < K; ++j) {
if (dist < karr[0][j]) {
for (int k = K-1; k > j; --k) {
karr[0][k] = karr[0][k-1];
karr[1][k] = karr[1][k-1];
}
karr[0][j] = dist;
karr[1][j] = label;
break;
}
}
}
// 多數決
float majority_vote(float *labels, int K) {
// 簡易計數:假設標籤為 0/1,可擴展為一般情況
int cnt0 = 0, cnt1 = 0;
for (int i = 0; i < K; ++i) labels[i] == 0 ? ++cnt0 : ++cnt1;
return cnt1 > cnt0 ? 1 : 0;
}
int main() {
int K=3, N, D;
float **data = loadData(&K, &D, &N); // 讀取 data.txt:首行 K=3,D=8,N=6
float *test = malloc((D-1)*sizeof(float));
while (1) {
printf("輸入 %d 維測試資料:", D-1);
for (int i=0;i
data.txt 範例(K=3, D=9, N=6,最後一欄為標籤):
1.0 1.1 1.2 2.1 0.3 2.3 1.4 0.5 1
1.7 1.2 1.4 2.0 0.2 2.5 1.2 0.8 1
1.2 1.8 1.6 2.5 0.1 2.2 1.8 0.2 1
1.9 2.1 6.2 1.1 0.9 3.3 2.4 5.5 0
1.0 0.8 1.6 2.1 0.2 2.3 1.6 0.5 1
1.6 2.1 5.2 1.1 0.8 3.6 2.4 4.5 0
輸入前 8 維特徵向量,程式正確輸出類別 1 或 0,驗證演算法有效性。
qsort 或堆(heap)將 K 近鄰維護從 O(NK) 降至 O(N log K)本實作展示了 KNN 核心邏輯的純 C 語言落地,適合作為機器學習入門與嵌入式部署的基礎參考。