K-Means 聚类算法C语言代码实现

1.具体代码实现如下

 #include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <sstream> 
using namespace std;
typedef struct  //点结构体
{
  double x;  //属性1
  double y;  //属性2
}Point;

float stringToFloat(string i){  
    stringstream sf;  
    float score=0;  
    sf<<i;  
    sf>>score;  
    return score;  
} 
int  main()
{
   vector<Point> vecPoint;   //所有点
   vector<Point> vecCenter;  //中心点
   vector<vector<Point> > vecCluster;  //簇1,2,...,n;

   int i,j,k;//循环变量
   int Num=0;//聚类中心数目 
   int Count=0;//输入坐标点的个数:Count/2; 
   int tempM[200]={0};
   cout <<"请输入聚类中心的数目K=?" <<endl;
   cin>>Num;
   
   Point temp;
   
   //1.开始读取文件数据  data.txt
  ifstream infile("data.txt");
  if(!infile)
     cout<<"Open file Error..."<<endl;
  //2.将文件中数据逐个读取:每行只能是坐标点的X或Y值,注意格式 
   string value; //value 临时变量,保存读取的数字 
   while(getline(infile,value)) 
   {
        tempM[Count]=stringToFloat(value);
        Count++;

   }

   for(i=0;i<Count;i=i+2) //初始化各个点
   {
      temp.x=tempM[i];
      temp.y=tempM[i+1];
      vecPoint.push_back(temp);
   }
   
   //3.初始化中心点,可以修改为随机选择Num个中心点 
   int srandNum=0;
   for(i=0;i<Num;i++)
   {
      srandNum=rand()%Count; 
      temp.x=tempM[srandNum];
      temp.y=tempM[srandNum+1];
      vecCenter.push_back(temp);
   }
   
   //4.开始聚类运算 
    double distance; //距离
   double mindistance;
   unsigned int flag;  //簇类id
   unsigned int round=1;  //迭代轮次;
   double errorSum1;  //误差平方和
   double errorSum2;  //误差平方和
   vector<Point> tempvec;
   //double distance1,distance2,distance3;
   for(i=0;i<Num;i++)   //初始化Cluster vector
   {
      vecCluster.push_back(tempvec);
   }
   
   //自动聚类 
   do
   {
      for( i=0;i<vecCluster.size();i++)  //清空每一个簇对应的容器
      {
         vecCluster[i].clear();
      }
      for( i=0;i<Count/2;i++)    //对数据对象进行归类
      {
         mindistance=sqrt(pow(vecPoint[i].x-vecCenter[0].x,2.0)+pow(vecPoint[i].y-vecCenter[0].y,2.0));
         flag=0;
         for(int k=1;k<Num;k++)   //与Num个中心点比较距离   
         {
            distance=sqrt(pow(vecPoint[i].x-vecCenter[k].x,2.0)+pow(vecPoint[i].y-vecCenter[k].y,2.0));
            if(distance<mindistance)  //离该簇的中心更近
            {
               flag=k;
               mindistance=distance;
            }
         }
         vecCluster[flag].push_back(vecPoint[i]);  //归类到相应的簇
      }// end of for(i=0;i<11;i++)
      
      cout<<"-------------第"<<round<<"次划分结果:-------------"<<endl;
      for( i=0;i<vecCluster.size();i++)  //输出该轮次的各个簇内的元素
      {
         cout<<"簇"<<i+1<<": ";
         for( j=0;j<vecCluster[i].size();j++)
         {
            cout<<"("<<vecCluster[i][j].x<<","<<vecCluster[i][j].y<<") ";
         }
         cout<<"最新聚类中心点:("<<vecCenter[i].x<<","<<vecCenter[i].y<<")";
         cout<<endl;
      }
      
      if(round==1)
      {
         //计算初始的簇内变差
         errorSum1=0;
         for( k=0;k<Num;k++)
         {
            for(i=0;i<vecCluster[k].size();i++)
            {
                errorSum1+=pow(vecCenter[k].x-vecCluster[k][i].x,2.0)+pow(vecCenter[k].y-vecCluster[k][i].y,2.0);
            }
         }
      }
      else
      {
         errorSum1=errorSum2;  //记录上一次的簇内变差
      }
      
      round++;  //轮次加1
      double sum_x,sum_y;
      vecCenter.clear();  //清空原来的簇中心集合
      for( k=0;k<Num;k++)   //重新计算簇类中心
      {
         sum_x=0;
         sum_y=0;
         for( i=0;i<vecCluster[k].size();i++)
         {
             sum_x+=vecCluster[k][i].x;
             sum_y+=vecCluster[k][i].y;
         }
         temp.x=sum_x/vecCluster[k].size();
         temp.y=sum_y/vecCluster[k].size();
         vecCenter.push_back(temp);  //加入新的簇中心
      }
      errorSum2=0;  //计算新的簇内变差

      
      for( k=0;k<Num;k++)
      {        
         for( i=0;i<vecCluster[k].size();i++)
         {
            errorSum2+=pow(vecCenter[k].x-vecCluster[k][i].x,2.0)+pow(vecCenter[k].y-vecCluster[k][i].y,2.0);
         }
      }
      /*
      distance1=fabs(vecCenter[0].x-vecCenter[3].x)+fabs(vecCenter[0].y-vecCenter[3].y);
      distance2=fabs(vecCenter[1].x-vecCenter[4].x)+fabs(vecCenter[1].y-vecCenter[4].y);
      distance3=fabs(vecCenter[2].x-vecCenter[5].x)+fabs(vecCenter[2].y-vecCenter[5].y);
      vecCenter.erase(vecCenter.begin(),vecCenter.begin()+3);
      */
   }while(fabs(errorSum2-errorSum1)>0.0000000001);   //簇内变差是否收敛稳定
    //}while(distance1||distance2||distance3);
    cout<<endl<<">>>各中心点已不变或簇内变差已收敛稳定,划分结束!!!"<<endl;
    cout<<"------------最终聚类结果:-------------"<<endl;
    for( i=0;i<vecCluster.size();i++)  //输出最终的聚类结果
    {
       cout<<"簇"<<i+1<<": ";
       for( j=0;j<vecCluster[i].size();j++)
       {
          cout<<"("<<vecCluster[i][j].x<<","<<vecCluster[i][j].y<<") ";
       }
       cout<<endl;
    }
    cout<<"Program Over Here ... "<<endl; 
    cout<<"Press <Enter>  To Exit..."<<endl;
   char  a='0';
   cin>>a;
    return 0; 
}
  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
以下是K-means聚类算法C语言实现步骤和核心代码(部分): 1. 首先需要定义一个结构体来表示数据点的坐标: ```c typedef struct { double x; double y; } Point; ``` 2. 接着需要定义一个函数来计算两个数据点之间的距离: ```c double distance(Point p1, Point p2) { double dx = p1.x - p2.x; double dy = p1.y - p2.y; return sqrt(dx * dx + dy * dy); } ``` 3. 然后需要定义一个函数来随机生成初始聚类中心点: ```c void initCentroids(int k, Point* centroids, int numPoints) { int i, j; for (i = 0; i < k; i++) { int index = rand() % numPoints; centroids[i] = points[index]; for (j = 0; j < i; j++) { if (centroids[i].x == centroids[j].x && centroids[i].y == centroids[j].y) { i--; break; } } } } ``` 4. 接着需要定义一个函数来将数据点分配到最近的聚类中心点: ```c void assignPointsToCentroids(int k, Point* centroids, int numPoints, int* assignments) { int i, j; for (i = 0; i < numPoints; i++) { double minDistance = DBL_MAX; int minIndex = -1; for (j = 0; j < k; j++) { double d = distance(points[i], centroids[j]); if (d < minDistance) { minDistance = d; minIndex = j; } } assignments[i] = minIndex; } } ``` 5. 然后需要定义一个函数来重新计算聚类中心点的位置: ```c void updateCentroids(int k, Point* centroids, int numPoints, int* assignments) { int i, j; for (i = 0; i < k; i++) { double sumX = 0.0; double sumY = 0.0; int count = 0; for (j = 0; j < numPoints; j++) { if (assignments[j] == i) { sumX += points[j].x; sumY += points[j].y; count++; } } if (count > 0) { centroids[i].x = sumX / count; centroids[i].y = sumY / count; } } } ``` 6. 最后需要定义一个函数来实现K-means聚类算法的主要逻辑: ```c void kMeansClustering(int k, Point* points, int numPoints, Point* centroids, int* assignments) { initCentroids(k, centroids, numPoints); int i; for (i = 0; i < MAX_ITERATIONS; i++) { assignPointsToCentroids(k, centroids, numPoints, assignments); updateCentroids(k, centroids, numPoints, assignments); } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坏码农来福

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值