K均值算法的c语言实现

时间:2021-10-23 22:28:54


l 算法:

第一步:选K个初始聚类中心,z1(1)z2(1)…,zK(1),其中括号内的序号为寻找聚类中心的迭代运算的次序号。聚类中心的向量值可任意设定,例如可选开始的K个模式样本的向量值作为初始聚类中心。

第二步:逐个将需分类的模式样本{x}按最小距离准则分配给K个聚类中心中的某一个zj(1)

假设i=j时,,则,其中k为迭代运算的次序号,第一次迭代k=1Sj表示第j个聚类,其聚类中心为zj。

第三步:计算各个聚类中心的新的向量值,zj(k+1)j=1,2,…,K

求各聚类域中所包含样本的均值向量:

其中Nj为第j个聚类域Sj中所包含的样本个数。以均值向量作为新的聚类中心,可使如下聚类准则函数最小:

在这一步中要分别计算K个聚类中的样本均值向量,所以称之为K-均值算法。

第四步:若,j=1,2,…,K,则返回第二步,将模式样本逐个重新分类,重复迭代运算;

若,j=1,2,…,K,则算法收敛,计算结束。


#include<stdio.h>
#include<malloc.h>
void classfication(int n,int dim,int c,int**sample,float**centre,int**category);
void newcentre(int n,int dim,int c,int**sample,float**centre,int**category);
void recordforecentre(int c,int dim,float**excentre,float**centre);
int testfinish(int c,int dim,float**excentre,float**centre);
int main()
{
int n=-1;
int dim=-1;
int c=-1;
int i=0;
int j=0;
printf("请输入样本数目.\n");
scanf("%d",&n);
printf("请输入样本维数.\n");
scanf("%d",&dim);
printf("请输入要分成的类的数目\n");
scanf("%d",&c);
if(c==1||c<=0){
printf("the input is invalid\n");
return 0; }
printf("please input the sample number.\n");
int**sample=(int**)malloc(n*sizeof(int*));
for( i=0;i<n;i++)
sample[i]=(int*)malloc(dim*sizeof(int));//分配内存
for( i=0;i<n;i++){
printf("the %dth number\n",i);
for(int j=0;j<dim;j++)
scanf("%d",&sample[i][j]);
}
float**centre=(float**)malloc(c*sizeof(float*));
for( i=0;i<c;i++)
centre[i]=(float*)malloc(dim*sizeof(float));//分配内存
float**excentre=(float**)malloc(c*sizeof(float*));
for( i=0;i<c;i++)
excentre[i]=(float*)malloc(dim*sizeof(float));//分配内存
for(i=0;i<c;i++)
for(j=0;j<dim;j++){
centre[i][j]=sample[i][j]; }//初始化聚类中心
int**category=(int**)malloc(c*sizeof(int*));
for( i=0;i<c;i++)
category[i]=(int*)malloc(n*sizeof(int));//分配内存

do{
classfication(n,dim,c,sample,centre,category);
recordforecentre(c,dim,excentre,centre); //记录聚类中心以便后期判别;
newcentre(n,dim, c, sample, centre,category);//计算新的聚类中心
} while(testfinish(c,dim,excentre,centre));//测试新的聚类中心和原来的聚类中心是否相同。
for(i=0;i<c;i++){
printf("the %dth category is consist of:" );
for(j=0;j<n;j++)
if(category[i][j]!=-1)
printf(" %d ",category[i][j]);
printf("\n");}
getchar();
return 0;
}
/*
本函数采用欧几里得最小距离进行分类*/
void classfication(int n,int dim,int c,int**sample,float**centre,int**category)
{
int i=0;
int j=0;
int k=0;
int t=0;
int cc=-1;
float min=-1;
float result=0;
for(i=0;i<c;i++)
for(j=0;j<n;j++)
category[i][j]=-1;
for(i=0;i<n;i++){
for(j=0;j<c;j++){
for(k=0;k<dim;k++){
result+=(sample[i][k]-centre[j][k])*(sample[i][k]-centre[j][k]);

}
if(min<0||min>result){
min=result;
cc=j;}
result=0;
}
while(category[cc][t]!=-1)
t++;
category[cc][t]=i;
t=0;
min=-1;
}
}
/*
本函数实现对原来聚类中心的记录*/
void recordforecentre(int c,int dim,float**excentre,float**centre)
{
int i=0;
int j=0;
for(i=0;i<c;i++)
for(j=0;j<dim;j++)
excentre[i][j]=centre[i][j];
}
/*
本函数实现对新聚类的计算采用的是书本上的方法*/
void newcentre(int n,int dim,int c,int**sample,float**centre,int**category)
{
int i=0;
int j=0;
int k=0;
int t=0;
int* sum=(int*)malloc(dim*sizeof(int));
for(t=0;t<dim;t++)
sum[t]=0;
for(i=0;i<c;i++){
j=0;
while(category[i][j]>=0)
{
for(k=0;k<dim;k++)
sum[k]+=sample[category[i][j]][k];
j++;
}
for(t=0;t<dim;t++)
centre[i][t]=(float)sum[t]/j;
for(t=0;t<dim;t++)
sum[t]=0;
}
}
/*
本函数实现对聚类中心的对比
*/
int testfinish(int c,int dim,float**excentre,float**centre)
{
int i=0;
int j=0;
for(i=0;i<c;i++)
for(j=0;j<dim;j++)
if(excentre[i][j]!=centre[i][j])
return 1;
return 0;
}









K均值算法的c语言实现