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