K-means聚类算法C语言代码
K-means聚类算法 也称K均值聚类算法 是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。
上图a表示最初的对象点的样本,在图b中我们首先假定k=2,即在样本空间区域随机选取两个坐标点,然后通过计算每个点与两个之间的距离大小分为两个类别,如图c所示,接着在每一组对象点当中计出中心坐标点,这样我们就得到了图d的两个新的坐标点,通过如此反复的迭代过程,最后结果趋于稳定,最终我们得到的两个类别如图f。
2.编程思路
首先我假设生成一个6*6的二维数组,通过产生随机数0/1的方式,随机产生一个带数值的二维数组,这些数值表示的是这是第几个对象点,如06,则表示第6个点为对象点,如果是00则表示该坐标没有对象点。
然后设定两个初始的坐标点,用来进行第一次的分类,通过计算每个对象点和两个坐标点的距离,划分成了2个类别—d1,d2数组。
接着分别在d1数组和d2数组中找出该组对象点的中心值坐标,这样就可以得到新的两个坐标点。
最后通过迭代算法,找出不再变化的坐标点则完成分类。
3.代码实现
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include <math.h>
main()
{
int i,j;
int a[6][6];
srand(time(0));//以时间为种子,每次生成不同的数
for(i=0;i<6;i++)
{
for(j=0;j<6;j++)
//随机生成0/1
a[i][j]=0+rand()%2;//rand()生成数的范围在[a,b)写成:a[i]=a+rand()%(b-a);
}
for(i=0;i<6;i++)
for(j=0;j<6;j++){
if(a[i][j]==1)
a[i][j]=i*6+j+1;
}
printf(" 随机生成对象点:\n");
for(i=0;i<6;i++)
for(j=0;j<6;j++){
if(j!=5)
printf(" %02d ",a[i][j]);
else
printf(" %02d \n",a[i][j]);
}
printf("\n");printf("\n");
int x[2]={1,1};//提前选取两个初始点
int y[2]={4,4};
int x1,x2,y1,y2;
int d1[36]={0};//通过点之间的距离分为两组聚集数组
int d2[36]={0};
int k=0;
int l=0;
for(i=0;i<6;i++)
for(j=0;j<6;j++){
if(a[i][j]!=0){
if(sqrt((i-x[0])*(i-x[0])+(j-x[1])*(j-x[1]))<sqrt((i-y[0])*(i-y[0])+(j-y[1])*(j-y[1]))){
d1[k]=a[i][j];
k++;
}
else{
d2[l]=a[i][j];
l++;
}
}
}
printf("通过两个初始点分类成两个聚集数组:\n");
printf("数组一:");
for(i=0;i<k;i++)
printf("%d ",d1[i]);
printf("\n");
printf("数组二:");
for(i=0;i<l;i++)
printf("%d ",d2[i]);
printf("\n");
int o=0;int p=0;
int q;//每个点的行号
for(i=0;i<k;i++){
q=(d1[i]-1)/6;
o=q+o;
p=d1[i]-q*6-1+p;
}
x[0]=o/k;x[1]=p/k;
o=0;p=0;
for(i=0;i<l;i++){
q=(d2[i]-1)/6;
o=q+o;
p=d2[i]-q*6-1+p;
}
y[0]=o/l;y[1]=p/l;
printf("\n");printf("\n");
printf("根据两个已分类的数组中心值新生成的两个坐标点:\n");
printf("%d,%d ",x[0],x[1]);
printf("%d,%d \n\n",y[0],y[1]);
while(1){
x1=x[0];x2=x[1];y1=y[0];y2=y[1];
for(i=0;i<36;i++){
d1[i]=0;d2[i]=0;}
k=0;
l=0;
for(i=0;i<6;i++)
for(j=0;j<6;j++){
if(a[i][j]!=0){
if(sqrt((i-x[0])*(i-x[0])+(j-x[1])*(j-x[1]))<sqrt((i-y[0])*(i-y[0])+(j-y[1])*(j-y[1]))){
d1[k]=a[i][j];
k++;
}
else{
d2[l]=a[i][j];
l++;
}
}
}
o=0;p=0;q=0;
for(i=0;i<k;i++){
q=(d1[i]-1)/6;
o=q+o;
p=d1[i]-q*6-1+p;
}
x[0]=o/k;x[1]=p/k;
o=0;p=0;q=0;
for(i=0;i<l;i++){
q=(d2[i]-1)/6;
o=q+o;
p=d2[i]-q*6-1+p;
}
y[0]=o/l;y[1]=p/l;
printf("根据两个已分类的数组中心值新生成的两个坐标点:\n");
printf("%d,%d ",x[0],x[1]);
printf("%d,%d \n\n",y[0],y[1]);
if(x1==x[0] && x2==x[1] && y1==y[0] && y2==y[1]){
printf("已找到最终的两个坐标点!");
break;
}
}
}
4.运行结果展示