#include<iostream>
#include<math.h>
#include<time.h>
#include<stdlib.h>
#include<vector>
const int Max=1000000; //点最多的数目
const double low_limit=0; //点的横纵坐标下限
const double high_limit=255;
using namespace std;
class Point //点类
{
private:
doubleX; //横坐标
doubleY; //纵坐标
public:
Point(doublea,double b):X(a),Y(b)
{
}
inlinedouble GetX() const
{
returnX;
}
inlinedouble GetY() const
{
returnY;
}
};
class Distance //计算点之间距离类
{
public:
doubleoperator()(const Point& one,const Point& other)
{
doublea=pow((one.GetX()-other.GetX()),2);
doubleb=pow((one.GetY()-other.GetY()),2);
returnsqrt(a+b);
}
};
class Cluster
{
private:
vector<Point>center;//中心点集
vector<Point>*association; //中心点所关联聚合点集,第i个位置上的点集关联与第i个中心点
vector<Point>pointset;//初始化点集
intk; //k个聚类
intn;
voidRemove(int index); //从pointset删除第index个点
doubleFromCenterSetTopoint(int index); //计算从初始化点到中心点集的距离和
intMaxLen(); //从初始化点集中选择一个与中心点集距离最大的点得索引号
voidSelectShortestDistance(int index); //从初始化点集中选择一个与中心点集距离最近的点,并把它加入关联点集
voidset_center(); //设置中心点集
voidset_associate(); //设置关联点集
public:
voidInit_PS(); //初始化点集
voidAdjust_Cluster();
voidShow_Cluster(); //显示聚类
};
void Cluster::Init_PS()
{
cout<<"请输入初始化点的数目:";
cin>>n;
if(!cin.good())
{
cout<<"输入不合法,程序终止!"<<endl;
cin.clear();
exit(0);
}
if(n>=Max)
{
cout<<"点的数目过大,程序终止!"<<endl;
exit(0);
}
inti;
doublex,y;
for(i=1;i<=n;i++)
{
cout<<"请输入第"<<i<<"个点的横坐标:";
cin>>x;
cout<<"请输入第"<<i<<"个点的纵坐标:";
cin>>y;
if(!cin.good())
{
cout<<"输入异常,程序终止!"<<endl;
cin.clear();
exit(0);
}
if(!(x<=high_limit&& x>=low_limit) || !(y<=high_limit && y>=low_limit))
{
cout<<"点的横纵坐标应该在"<<low_limit<<"到"<<high_limit<<"之间"<<endl;
i--;
cout<<"请重输该点坐标!"<<endl;
continue;
}
this->pointset.push_back(Point(x,y));
}
cout<<"请输入要生成聚类个数(必须在1到"<<n/2<<"之间):";
intt;
cin>>t;
if(!cin.good())
{
cout<<"输入异常,程序终止!"<<endl;
cin.clear();
exit(0);
}
if(!(t<=n/2&& t>=1))
{
cout<<"输入不合法,程序终止!"<<endl;
exit(0);
}
k=t;
this->association=newvector<Point>[k];
}
void Cluster::Remove(int index)
{
intj;
vector<Point>::iteratorit;
for(j=0,it=this->pointset.begin();it!=this->pointset.end();it++,j++)
{
if(j==index)break;
}
this->pointset.erase(it);
}
double Cluster::FromCenterSetTopoint(intindex)
{
vector<Point>::iteratorit;
if(this->center.empty())return 0;
Distanced;
doublelen=0;
for(it=this->center.begin();it!=this->center.end();it++)
{
len+=d(*it,this->pointset[index]);
}
returnlen;
}
int Cluster::MaxLen()
{
if(this->pointset.empty()|| this->center.empty()) return -1;
intindex,pos;
doublemaxLen=0;
vector<Point>::const_iteratorit;
for(index=0,it=this->pointset.begin();it!=this->pointset.end();index++,it++)
{
if(this->FromCenterSetTopoint(index)>maxLen)
{
maxLen=this->FromCenterSetTopoint(index);
pos=index;
}
}
returnpos;
}
void Cluster::set_center()
{
inti;
for(i=1;i<=k;i++)
{
if(this->center.empty())//中心点集为空
{
srand((unsigned)time(0));//从初始化点集随机选择一个点
intt=rand()%k;
if(t>0)t--; //使得t能够等于0
this->center.push_back(this->pointset[t]);
this->Remove(t);//从pointset中删除此点
}
else
{
intindex=this->MaxLen(); //index指向pointset中与中心点集距离最大的点的位置
this->center.push_back(this->pointset[index]);//将此点加入当前中心点集
this->Remove(index);
}
}
}
void Cluster::SelectShortestDistance(intindex)
{
doubleshortestDistance=Max;
vector<Point>::iteratorit;
vector<Point>::iteratorpos; //指向中心点集合中与index所指向的点集合中某个点
Distanced;
doublelen;
for(it=this->center.begin();it!=this->center.end();it++)
{
len=d(*it,this->pointset[index]);
if(len<shortestDistance)
{
shortestDistance=len;
pos=it;
}
}
inti=pos-this->center.begin(); //i表示中心点集第i个点与index所指向的点集合中点距离最小
this->association[i].push_back(this->pointset[index]);//加入第i个关联点集
}
void Cluster::set_associate()
{
vector<Point>::iteratorit;
intindex;
for(index=0,it=this->pointset.begin();it!=this->pointset.end();it++,index++)
{
this->SelectShortestDistance(index);
}
}
void Cluster::Adjust_Cluster()
{
this->set_center();
this->set_associate();
}
void Cluster::Show_Cluster()
{
vector<Point>::const_iteratorit;
inti=0;
Distanced;
for(it=this->center.begin();it!=this->center.end();it++,i++)
{
cout<<"第"<<i<<"个聚类"<<endl;
cout<<"第"<<i<<"个中心点是:";
cout<<"("<<it->GetX()<<","<<it->GetY()<<")"<<endl;
cout<<"它所关联的聚类是:"<<endl;
vector<Point>::const_iteratorpos;
for(pos=this->association[i].begin();pos!=this->association[i].end();pos++)
{
intindex=pos-this->association[i].begin();
cout<<"第"<<index<<"个点是:"<<"("<<pos->GetX()<<","<<pos->GetY()<<")"<<endl;
cout<<"它与中心点的距离是:"<<d(*it,*pos)<<endl;
}
}
}
void main()
{
Clustercc;
cc.Init_PS();
cc.Adjust_Cluster();
cc.Show_Cluster();
}