c语言实现KNN算法,
可以实现任意维度,任意数据量,任意分类数据的KNN算法。
K值的修改在KNN.h文件
main.c
#include <stdio.h>
#include <stdlib.h>
#include "KNN.h"
#include "array.h"
int main(void)
{
//初始化 ,读取数据
//count为分类数
//N为数据个数,M为数据维度,dist为数据间距
//array为导入的原始数据,testdata为测试数据,karray为测试数据到各个原始数据之间的距离
int i,j,count=1;
int N=0,M=0;
float temp;
float dist;
float **array = NULL,**karray = NULL,*testdata;
KNN_load_data(&N,&M,&array,&karray);
printf("读取数据个数:%d,数据维度:%d\n",N,M-1);
printf("读入的数据为:\n");
print_2Darray(*array,N,M);
//判断所给数据共有几个类
float a[N-1];
for(i=0;i<N-1;i++)
{
a[i] = array[i][M-1];
}
bubble_sort(a,N);
for(i=0;i<N-1;i++)
{
if(a[i]!=a[i+1])
{
count++;
}
}
printf("所给数据的分类数为:%d\n",count);
//写入待测数据点
testdata = (float *)malloc((M-1) * sizeof(float));
printf("写入一个%d维的待测数据点:",M-1);
for(i=0;i<M-1;i++)
{
scanf("%f",&testdata[i]);
}
//计算距离
for(i=0;i<N;i++)
{
dist = distance(M-1,testdata,array[i]);
karray[i][0] = dist;
karray[i][1] = array[i][M-1];
}
printf("待测点到各个点的距离:\n");
print_2Darray(*karray,N,2);
//冒泡排序
for(i=0;i<N-1;i++)
{
for(j=0;j<N-i-1;j++)
{
if(karray[j][0]>karray[j+1][0])
{
temp = karray[j][0];
karray[j][0] = karray[j+1][0];
karray[j+1][0] = temp;
temp = karray[j][1];
karray[j][1] = karray[j+1][1];
karray[j+1][1] = temp;
}
}
}
printf("排序后的待测点到各个点的距离:\n");
print_2Darray(*karray,N,2);
//找出前K个距离最近的进行分类
//result储存各个分类出现的频率
float *result;
int b = count;
result = (float *)malloc(count*sizeof(float));
for(i=0;i<K;i++)
{
for(b = count;b>0;b--)
{
if((int)(karray[i][1]) == b-1)
{
result[b-1] ++;
}
}
}
printf("K取%d\n",K);
printf("最终各分类出现的次数:");
print_1Darray(result,count);
//最终结果输出
int index;
index = max_index(result,count);
printf("\n最终判断改测试数据属于%d类",index);
return 0;
}
array.h
void selection_sort(float *array , int len);
void bubble_sort(float *array , int len);
void print_1Darray(float *array,int len);
void print_2Darray(float *array,int N,int M);
void swap(float *a,float *b);
int max_index(float *a,int len);
float distance(int dimension,float *av,float *bv);
array.c
#include<stdio.h>
#include"array.h"
#include<math.h>
void print_1Darray(float *array,int len)
{
//array是需要打印的数组,len为该数组的长度
int i;
printf("[");
for(i=0;i<len;i++)
{
printf("%.2f",array[i]);
printf("%c",i<len-1?' ':']');
}
printf("\n");
}
void print_2Darray(float *array,int N , int M)
{
int i=0,j=0;
for(i=0;i<N;i++)
{
for(j=0;j<M;j++)
{
printf("%.2f%c",array[i*M+j],j==M-1?'\n':' ');
}
}
}
void selection_sort(float *array,int len)
{
int i,j;
for(i=0;i<len-1;i++)
{
for(j=i+1;j<len;j++)
{
if(array[j]>array[i])
{
swap(&array[j],&array[i]);
}
}
}
}
void bubble_sort(float *array,int len)
{
int i,j;
for(i=0;i<len-1;i++)
{
for(j=0;j<len-1-i;j++)
{
if(array[j+1]>array[j]) swap(&array[j+1],&array[j]);
}
}
}
void swap(float *a,float *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int max_index(float *a,int len)
{
int max = a[0];
int index=0,i;
for(i=1;i<len;i++)
{
if(max<a[i])
{
max = a[i];
index = i;
}
}
return index;
}
float distance(int dim,float *av, float *bv) //dim代表两个向量的维度
{
int i,dist=0;
for(i=0;i<dim;i++)
{
dist += pow(av[i]-bv[i],2);
}
return sqrt(dist);
}
KNN.h
#define K 3
void KNN_load_data(int *data_num,int *dimension,float ***array,float ***karray);
float **dynamic_array(int n,int m);
KNN.c
#include<stdio.h>
#include<stdlib.h>
#include"KNN.h"
#include"array.h"
//创建动态二维数组
float **dynamic_array(int n,int m)//n是数据个数,m是维数
{
int i;
float **array;
array=(float **)malloc(n*sizeof(float *));
array[0]=(float *)malloc(n*m*sizeof(float));
for(i=1;i<n;i++)
{
array[i] = array[i-1] + m;
}
return array;
}
void KNN_load_data(int *data_num,int *dimension,float ***array,float ***karray)
{
FILE *fp;
int i=0,j=0;
if((fp = fopen("data.txt","r")) == NULL) printf("文件打开失败\n");
if((fscanf(fp,"N=%d,D=%d",data_num,dimension)) != 2) printf("文件打开失败\n");
*array = dynamic_array(*data_num,*dimension);
*karray = dynamic_array(*data_num,2);
for(i=0;i<*data_num;i++)
{
for(j=0;j<*dimension;j++)
{
fscanf(fp,"%f",&(*array)[i][j]);
}
}
for(i=0;i<*data_num;i++)
{
for(j=0;j<2;j++)
{
(*karray)[i][j]=999.0;
}
}
}
data.txt
N=6,D=9
N=7,D=9
2.0 2.1 5.2 4.1 0.5 5.3 2.4 2.1 2
1.1 3.1 2.3 3.0 3.2 4.4 3.3 1.8 1
1.7 3.2 3.2 2.1 4.4 3.5 4.3 1.2 0
1.1 1.5 5.2 5.2 3.5 1.2 5.3 3.5 1
2.0 2.1 3.2 4.7 2.4 2.4 4.4 4.5 0
2.6 3.2 3.1 5.2 1.2 7.4 1.2 3.4 2
2.1 1.1 2.2 3.7 1.4 3.4 3.4 3.5 0
程序的最终结果