K均值算法的c语言实现


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;
 }
 
 
 
 








  • 2
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是用 C 语言实现 K 均值算法的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <math.h> #define MAX_ITERATIONS 100 // 最大迭代次数 #define NUM_POINTS 10 // 数据点数量 #define NUM_CLUSTERS 2 // 聚类数量 // 定义数据点结构体 typedef struct { double x, y; } Point; // 计算两个点之间的距离 double distance(Point p1, Point p2) { double dx = p1.x - p2.x; double dy = p1.y - p2.y; return sqrt(dx * dx + dy * dy); } // 初始化聚类中心点 void init_clusters(Point* data, Point* clusters) { // 将前两个数据点作为初始聚类中心点 clusters[0] = data[0]; clusters[1] = data[1]; } // 将数据点划分到最近的聚类中心点 void classify_points(Point* data, Point* clusters, int* assignments) { for (int i = 0; i < NUM_POINTS; i++) { double min_distance = INFINITY; int min_index = -1; for (int j = 0; j < NUM_CLUSTERS; j++) { double d = distance(data[i], clusters[j]); if (d < min_distance) { min_distance = d; min_index = j; } } assignments[i] = min_index; } } // 重新计算聚类中心点 void update_clusters(Point* data, Point* clusters, int* assignments) { int counts[NUM_CLUSTERS] = {0}; double sum_x[NUM_CLUSTERS] = {0.0}; double sum_y[NUM_CLUSTERS] = {0.0}; for (int i = 0; i < NUM_POINTS; i++) { int cluster = assignments[i]; counts[cluster]++; sum_x[cluster] += data[i].x; sum_y[cluster] += data[i].y; } for (int j = 0; j < NUM_CLUSTERS; j++) { if (counts[j] > 0) { clusters[j].x = sum_x[j] / counts[j]; clusters[j].y = sum_y[j] / counts[j]; } } } // 打印聚类结果 void print_clusters(Point* clusters) { printf("Clusters:\n"); for (int i = 0; i < NUM_CLUSTERS; i++) { printf("(%f, %f)\n", clusters[i].x, clusters[i].y); } } int main() { // 初始化数据点 Point data[NUM_POINTS] = {{1, 1}, {2, 1}, {4, 3}, {5, 4}, {7, 5}, {10, 7}, {11, 5}, {12, 6}, {14, 7}, {15, 5}}; // 初始化聚类中心点 Point clusters[NUM_CLUSTERS]; init_clusters(data, clusters); // 迭代计算聚类结果 int assignments[NUM_POINTS]; for (int i = 0; i < MAX_ITERATIONS; i++) { classify_points(data, clusters, assignments); update_clusters(data, clusters, assignments); } // 打印聚类结果 print_clusters(clusters); return 0; } ``` 这个示例代码演示了如何使用 K 均值算法将 10 个二维数据点划分为 2 个聚类

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值