zoukankan      html  css  js  c++  java
  • k近邻算法(knn)的c语言实现

      最近在看knn算法,顺便敲敲代码。

     

      knn属于数据挖掘的分类算法。基本思想是在距离空间里,如果一个样本的最接近的k个邻居里,绝大多数属于某个类别,则该样本也属于这个类别。俗话叫,“随大流”。

      简单来说,KNN可以看成:有那么一堆你已经知道分类的数据,然后当一个新的数据进入的时候,就开始跟训练里的每个点求距离,然后挑出离这个数据最近的K个点,看看这K个点属于什么类型,然后用少数服从多数的原则,给新数据归类。

      该算法的示意图,简单明了:

      

        下面的算法步骤取自于百度文库(文库是一个好东西),代码是参照这个思路实现的:

       

      code:

      1 #include<stdio.h>
      2 #include<math.h>
      3 #include<stdlib.h>
      4 
      5 #define K 3 //近邻数k
      6 typedef float type;
      7 
      8 //动态创建二维数组
      9 type **createarray(int n,int m)
     10 {
     11     int i;
     12     type **array;
     13     array=(type **)malloc(n*sizeof(type *));
     14     array[0]=(type *)malloc(n*m*sizeof(type));
     15     for(i=1;i<n;i++) array[i]=array[i-1]+m;
     16     return array;
     17 }
     18 //读取数据,要求首行格式为 N=数据量,D=维数
     19 void loaddata(int *n,int *d,type ***array,type ***karray)
     20 {
     21     int i,j;
     22     FILE *fp;
     23     if((fp=fopen("data.txt","r"))==NULL)    fprintf(stderr,"can not open data.txt!\n");
     24     if(fscanf(fp,"N=%d,D=%d",n,d)!=2)    fprintf(stderr,"reading error!\n");
     25     *array=createarray(*n,*d);
     26     *karray=createarray(2,K);
     27 
     28     for(i=0;i<*n;i++)
     29         for(j=0;j<*d;j++)
     30             fscanf(fp,"%f",&(*array)[i][j]);    //读取数据
     31 
     32     for(i=0;i<2;i++)
     33         for(j=0;j<K;j++)
     34             (*karray)[i][j]=9999.0;    //默认的最大值
     35     if(fclose(fp))    fprintf(stderr,"can not close data.txt");
     36 }
     37 //计算欧氏距离
     38 type computedistance(int n,type *avector,type *bvector)
     39 {
     40     int i;
     41     type dist=0.0;
     42     for(i=0;i<n;i++)
     43         dist+=pow(avector[i]-bvector[i],2);
     44     return sqrt(dist);
     45 }
     46 //冒泡排序
     47 void bublesort(int n,type **a,int choice)
     48 {
     49     int i,j;
     50     type k;
     51     for(j=0;j<n;j++)
     52         for(i=0;i<n-j-1;i++){
     53             if(0==choice){
     54                 if(a[0][i]>a[0][i+1]){
     55                     k=a[0][i];
     56                     a[0][i]=a[0][i+1];
     57                     a[0][i+1]=k;
     58                     k=a[1][i];
     59                     a[1][i]=a[1][i+1];
     60                     a[1][i+1]=k;
     61                 }
     62             }
     63             else if(1==choice){
     64                 if(a[1][i]>a[1][i+1]){
     65                     k=a[0][i];
     66                     a[0][i]=a[0][i+1];
     67                     a[0][i+1]=k;
     68                     k=a[1][i];
     69                     a[1][i]=a[1][i+1];
     70                     a[1][i+1]=k;
     71                 }
     72             }
     73         }
     74 }
     75 //统计有序表中的元素个数
     76 type orderedlist(int n,type *list)
     77 {
     78     int i,count=1,maxcount=1;
     79     type value;
     80     for(i=0;i<(n-1);i++) {
     81         if(list[i]!=list[i+1]) {
     82             //printf("count of %d is value %d\n",list[i],count);
     83             if(count>maxcount){
     84                 maxcount=count;
     85                 value=list[i];
     86                 count=1;
     87             }
     88         }
     89         else
     90             count++;
     91     }
     92     if(count>maxcount){
     93             maxcount=count;
     94             value=list[n-1];
     95     }
     96     //printf("value %f has a Maxcount:%d\n",value,maxcount);
     97     return value;
     98 }
     99 
    100 int main()
    101 {
    102     int i,j,k;
    103     int D,N;    //维度,数据量
    104     type **array=NULL;  //数据数组
    105     type **karray=NULL; //  K近邻点的距离及其标签
    106     type *testdata; //测试数据
    107     type dist,maxdist;
    108 
    109     loaddata(&N,&D,&array,&karray);
    110     testdata=(type *)malloc((D-1)*sizeof(type));
    111     printf("input test data containing %d numbers:\n",D-1);
    112     for(i=0;i<(D-1);i++)    scanf("%f",&testdata[i]);
    113 
    114     while(1){
    115     for(i=0;i<K;i++){
    116         if(K>N) exit(-1);
    117         karray[0][i]=computedistance(D-1,testdata,array[i]);
    118         karray[1][i]=array[i][D-1];
    119         //printf("first karray:%6.2f  %6.0f\n",karray[0][i],karray[1][i]);
    120     }
    121 
    122     bublesort(K,karray,0);
    123     //for(i=0;i<K;i++)    printf("after bublesort in first karray:%6.2f  %6.0f\n",karray[0][i],karray[1][i]);
    124     maxdist=karray[0][K-1]; //初始化k近邻数组的距离最大值
    125 
    126     for(i=K;i<N;i++){
    127         dist=computedistance(D-1,testdata,array[i]);
    128         if(dist<maxdist)
    129             for(j=0;j<K;j++){
    130                 if(dist<karray[0][j]){
    131                     for(k=K-1;k>j;k--){ //j后元素复制到后一位,为插入做准备
    132                         karray[0][k]=karray[0][k-1];
    133                         karray[1][k]=karray[1][k-1];
    134                     }
    135                     karray[0][j]=dist;  //插入到j位置
    136                     karray[1][j]=array[i][D-1];
    137                     //printf("i:%d  karray:%6.2f %6.0f\n",i,karray[0][j],karray[1][j]);
    138                     break;  //不比较karray后续元素
    139                 }
    140             }
    141         maxdist=karray[0][K-1];
    142         //printf("i:%d  maxdist:%6.2f\n",i,maxdist);
    143     }
    144     //for(i=0;i<K;i++)    printf("karray:%6.2f  %6.0f\n",karray[0][i],karray[1][i]);
    145     bublesort(K,karray,1);
    146     //for(i=0;i<K;i++)    printf("after bublesort in karray:%6.2f  %6.0f\n",karray[0][i],karray[1][i]);
    147     printf("\nThe data has a tag: %.0f\n\n",orderedlist(K,karray[1]));
    148 
    149     printf("input test data containing %d numbers:\n",D-1);
    150     for(i=0;i<(D-1);i++)    scanf("%f",&testdata[i]);
    151     }
    152     return 0;
    153 }

      实验:

      训练数据data.txt:

      N=6,D=9
      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

      预测数据:

      1.0 1.1 1.2 2.1 0.3 2.3 1.4 0.5

      1.7 1.2 1.4 2.0 0.2 2.5 1.2 0.8

      1.2 1.8 1.6 2.5 0.1 2.2 1.8 0.2

      1.9 2.1 6.2 1.1 0.9 3.3 2.4 5.5

      1.0 0.8 1.6 2.1 0.2 2.3 1.6 0.5

      1.6 2.1 5.2 1.1 0.8 3.6 2.4 4.5 

       

      程序测试的结果:

      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

      实验截图:

      

  • 相关阅读:
    Java实现 LeetCode 61 旋转链表
    Java实现 LeetCode 60 第k个排列
    Java实现 LeetCode 60 第k个排列
    Java实现 LeetCode 60 第k个排列
    Java实现 LeetCode 59 螺旋矩阵 II
    VC 2005 解决方案的目录结构设置和管理
    Visual C++ 设置适合自己的解决方案目录结构
    瑞蓝RL-NDVM-A16网络视频解码器 视频上墙解决方案专家--数字视频解码矩阵
    为什么类的定义中不能包含其自身类型,但是能包含其自身的指针或引用类型
    C++模板使用介绍
  • 原文地址:https://www.cnblogs.com/LCcnblogs/p/6031218.html
Copyright © 2011-2022 走看看