k-means算法

#include<cstdio>
#include<cmath>
struct node
{
    double x,y;
    int bl;//bl属性储存每个点属于哪个簇 
}a[105],b[105],c[15];//a代表原始的点,b表示重新分配后的簇,c代表簇中心 
double dist(node x,node y)
{
    return sqrt( (x.x-y.x) * (x.x-y.x) + (x.y-y.y) * (x.y-y.y) );
}
int main()
{
    int n,k,t;
    scanf("%d %d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%lf%lf",&a[i].x,&a[i].y);
        a[i].bl=i;
        b[i]=a[i];
    }
    /*
    for(int i=1;i<=k;i++)//指定初始簇中心 
    {
        scanf("%d",&t);
        c[i]=a[t];
    }
    */
    for(int i=1;i<=k;i++) c[i]=a[i];//不指定则使用前k个点做簇中心 
    while(1)
    {
        for(int i=1;i<=n;i++)//重新分配每个点所在的簇 
        {
            double dis=dist(b[i],c[1]);
            b[i].bl=1;
            for(int j=2;j<=k;j++)
            {
                if(dist(b[i],c[j])<dis)
                {
                    dis=dist(b[i],c[j]);
                    b[i].bl=j;
                }    
            }
        }
        for(int i=1;i<=k;i++)//计算新的簇中心 
        {
            double sumx=0,sumy=0;
            int cnt=0;
            for(int j=1;j<=n;j++)
            {
                if(b[j].bl==i)
                {
                    sumx+=b[j].x;
                    sumy+=b[j].y;
                    cnt++;
                }
            }
            c[i].x=sumx/cnt;
            c[i].y=sumy/cnt;
        }
        int flg=1;
        for(int i=1;i<=n;i++)//比较与上一轮分配结果是否有差异 
        {
            if(b[i].bl!=a[i].bl) flg=0;
        }
        if(flg) break;
        for(int i=1;i<=n;i++) a[i]=b[i];
    }
    //for(int i=1;i<=n;i++) printf("%lf %lf %d\n",b[i].x,b[i].y,b[i].bl);
    for(int i=1;i<=k;i++)
    {
        printf("第%d个簇:",i);
        for(int j=1;j<=n;j++)
        {
            if(b[j].bl==i) printf("%d ",j);
        }
        printf("\n");
    }
    return 0;
}
/*
样例数据: 
8 2
1 1
2 1
1 2
2 2
4 3
5 3
4 4
5 4
*/

 

posted @ 2022-04-22 09:12  Excim  阅读(33)  评论(0编辑  收藏  举报