C均值聚类算法的C语言实现

/**
C均值聚类算法的C语言实现
Author:AnranWu
Date:2020/11/25 
*/ 
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll maxn=1e6+50;
const double eps=1e-2;

struct node{
	double x=0,y=0;
}a[maxn],b[maxn],sum[maxn];

int belong[maxn],cnt[maxn];

double dis(node a,node b){
	return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

int main(){
	int c,n;
	printf("请输入需要将模式分为的类别数 c :"); 
	scanf("%d",&c);
	printf("请输入模式总数 n :"); 
	scanf("%d",&n);//输入需要聚类的模式数 
	printf("请输入各模式的两个特征点 :\n"); 
	for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);//输入每个模式的两个特征 
	for(int i=1;i<=c;i++)b[i]=a[i];//选定初始的c个聚类中心 
	int ans=0;//ans表示与上次聚类中心一致的聚类中心点数量,当所有聚类中心均不发生改变时循环结束 
	while(ans<c){
		memset(cnt,0,sizeof(cnt));//cnt记录每一个类别有多少个模式属于该类 
		for(int i=1;i<=n;i++){
			double minn=4e18;//计算该模式到每一个聚类中心的距离
			int mini=0;
			for(int j=1;j<=c;j++){
				double dis_to_center=dis(a[i],b[j]);
				if(dis(a[i],b[j])<minn){
					minn=dis_to_center;
					mini=j;
				}
			}
			belong[i]=mini;//选择距离最小的一个类加入该类 
			cnt[mini]++;//更新该类中模式的数量 
		}
		for(int i=1;i<=c;i++)sum[i].x=0,sum[i].y=0;
		for(int i=1;i<=n;i++){
			sum[belong[i]].x+=a[i].x;
			sum[belong[i]].y+=a[i].y;//计算新的聚类中心 
		}
		ans=0;
		for(int i=1;i<=c;i++){
			sum[i].x/=cnt[i];
			sum[i].y/=cnt[i];
			//判断该聚类中心是否发生变化,eps控制容差值 
			if((fabs(sum[i].x-b[i].x)<eps)&&(fabs(sum[i].y-b[i].y)<eps))ans++;
			b[i].x=sum[i].x; 
			b[i].y=sum[i].y;//更新聚类中心 
		}
	}
	printf("C均值聚类算法已经完成!\nc个类中心分别为\n");
	for(int i=1;i<=c;i++){
		printf("第%d类的聚类中心的两个特征值分别为 %.2lf %.2lf\n",b[i].x,b[i].y); 
	}
	for(int i=1;i<=c;i++){
		printf("属于第%d类的点有:\n"); 
		for(int j=1;j<=n;j++){
			if(belong[j]==i)printf("%d号点 %.2lf %.2lf\n",j,a[j].x,a[j].y);
		}
		putchar(10);
	}
}

/*
测试数据 #1
2
20
0 0
1 0
0 1
1 1
2 1
1 2
2 2
3 2
6 6
7 6
8 6
6 7
7 7
8 7
9 7
7 8
8 8
9 8
8 9
9 9
*/
posted @ 2020-11-25 15:54  AnranWu  阅读(746)  评论(0编辑  收藏  举报