//咱走的不是流量,走的是心
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<fstream>
#include<cstdio>
using namespace std;
#define Length 5 //数据维数(每个数据集,5维向量)
#define K 5 //类别数(分为5类)
#define Psize 50 //数据集总量
#define T 100 //根据实验要求选择迭代次数
#define End 0.00001 //结束条件
typedef struct
{
double p[Length];//存储数据向量
double distance[K];//存储距离不同类中心的距离
}Point;
typedef struct
{
Point clu_cent[K];//簇类中心
int cluster[K][Psize];//记录属于K簇的样本编号
int cluster_num[K];//记录属于K簇的样个个数
data与old_data为了计算聚类之前和聚类之后的变化,如果变化小,则停止聚类,说明比较收敛
double data;
double old_data;
}Cluster_Center;
Point all_data[Psize];//数据大小
Cluster_Center sample;
//自动生成样本数据
void rand_data()
{
int sum=50;
srand(time(0));
ofstream outfile,fout;
outfile.open("G:\\test.data");
int s[5];
while(sum)
{
for(int i=0;i<5;i++)
s[i]=rand()%100;
outfile<<s[0]<<" "<<s[1]<<" "<<s[2]<<" "<<s[3]<<" "<<s[4]<<endl;//将输出写入到文件中,所有cout的函数都可以用
sum--;
}
outfile.close();
}
//将样本数据读入内存
void input_data()
{
FILE *infile;
int i,j;
double data;
if((infile=fopen("G:\\test.data","r"))==NULL)
{
cout<<"没有test.data这个文件,无法导入数据"<<endl;
exit(1);
}
for(i=0;i<Psize;i++)//数据集的大小
{
for(j=0;j<Length;j++)//每条数据集中的个数
{
fscanf(infile,"%lf",&data);
all_data[i].p[j]=data; //存入到all_data中去。
// cout<<data<<" ";
}
// cout<<endl;
}
fclose(infile);//关闭文件描述符
}
//检查数据是否相等
int Equal(int a[],int n,int b)
{
for(int i=0;i<n;i++)
if(a[i]==b) return 1;
return 0;
}
//随机初始化聚类质心(要检测聚类中心不能相同)
void Init_center()
{
int sum=0;
int rand_num;
int center[K];
//随机产生三个0~Psize的数
while(sum<K)
{
rand_num=rand()%Psize;//设定中心标号
if(!Equal(center,sum,rand_num))
{
center[sum++]=rand_num;
}
}
for(int i=0;i<K;i++)//中心数据放到center中
{
for(int j=0;j<Length;j++)
{
sample.clu_cent[i].p[j]=all_data[center[i]].p[j];//重新赋值
}
}
}
//欧几里得距离公式
double Euclidean_Distance(int a,int b)//a代表的是样本数据,b代表的是簇中心数据
{
double square=0;
for(int i=0;i<Length;i++)
{
square+=pow((all_data[a].p[i]-sample.clu_cent[b].p[i]),2);
}
/*
for(int i=0;i<n;i++)//n维向量
{
square+=(a[i]-b[i])*(a[i]-b[i]);
}
*/
return sqrt(square);
}
//计算Psize组数据到K个质心的欧几里得距离
void claculate_distance()
{
int i,j;
for(i=0;i<Psize;i++)
for(j=0;j<K;j++)
{
all_data[i].distance[j]=Euclidean_Distance(i,j);//传递的是向量的标号
}
}
//将数据进行聚类
void cluster()
{
double minV;
for(int i=0;i<K;i++) //初始化每个簇中心中的数据为0
sample.cluster_num[i]=0;
for(int i=0;i<Psize;i++)
{
int index=0;
minV=all_data[i].distance[0];
for(int j=1;j<K;j++)//筛选到簇心欧几里得最小的
{
if(all_data[i].distance[j]<minV)
{
minV=all_data[i].distance[j];
index=j;
}
}
//划分簇集:记录每个簇中样本的总个数
//sample.cluster_num[index]存储的是该类总的样本的当前总数
sample.cluster[index][sample.cluster_num[index]++]=i;
}
double tem=0;
//计算样本误差和
for(int i = 0; i < K; i++)
for(int j = 0; j < sample.cluster_num[i]; j++){
tem +=pow(all_data[sample.cluster[i][j]].distance[i],2);
}
sample.old_data = sample.data;
sample.data =tem;
}
//重新计算类中心,按照列进行计算
void new_center()
{
int i, j, n;
double tmp_sum;
for(i = 0; i < K; i++)//簇中心
for(j = 0; j < Length; j++)//向量维数
{
tmp_sum = 0;
for(n = 0; n < sample.cluster_num[i]; n++) //第i个簇的第j维数的所有数据和&&求平均值
{
//sample.cluster[i][n]存储的是样本的编号
tmp_sum += all_data[sample.cluster[i][n]].p[j];
}
//取平均数得到新的簇中心
sample.clu_cent[i].p[j] = tmp_sum / sample.cluster_num[i];
}
}
//输出实验结果
void output()
{
for(int i=0;i<K;i++)
{
cout<<"第"<<i<<"类为:"<<endl;
for(int k=0;k<sample.cluster_num[i];k++)//sample.cluster_num[i]记录的是该类中,样本量的个数
{
for(int j=0;j<Length;j++)//Length每条样本长度
{
//sample.cluster[i][k]记录样本标号
cout<<all_data[sample.cluster[i][k]].p[j]<<" ";
}
cout<<endl;
}
}
}
int main()
{
int iteration;
double differ = 1;
int flag = 0;
rand_data();//生成样本数据
input_data();//将样本输入读入内存
Init_center();//初始化类中心
iteration=0;//迭代标记,T=100,即迭代次数为100,可自己设定
while(1)
{
claculate_distance(); //计算欧几里德距离
cluster(); //根据距离聚类
differ = sample.old_data - sample.data; /* 判断条件 */
differ = fabs(differ);
if(differ<=End||iteration>T)
break;
new_center();//重新计算类中心
}
output(); /* 聚类后显示结果 */
return 0;
}
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<fstream>
#include<cstdio>
using namespace std;
#define Length 5 //数据维数(每个数据集,5维向量)
#define K 5 //类别数(分为5类)
#define Psize 50 //数据集总量
#define T 100 //根据实验要求选择迭代次数
#define End 0.00001 //结束条件
typedef struct
{
double p[Length];//存储数据向量
double distance[K];//存储距离不同类中心的距离
}Point;
typedef struct
{
Point clu_cent[K];//簇类中心
int cluster[K][Psize];//记录属于K簇的样本编号
int cluster_num[K];//记录属于K簇的样个个数
data与old_data为了计算聚类之前和聚类之后的变化,如果变化小,则停止聚类,说明比较收敛
double data;
double old_data;
}Cluster_Center;
Point all_data[Psize];//数据大小
Cluster_Center sample;
//自动生成样本数据
void rand_data()
{
int sum=50;
srand(time(0));
ofstream outfile,fout;
outfile.open("G:\\test.data");
int s[5];
while(sum)
{
for(int i=0;i<5;i++)
s[i]=rand()%100;
outfile<<s[0]<<" "<<s[1]<<" "<<s[2]<<" "<<s[3]<<" "<<s[4]<<endl;//将输出写入到文件中,所有cout的函数都可以用
sum--;
}
outfile.close();
}
//将样本数据读入内存
void input_data()
{
FILE *infile;
int i,j;
double data;
if((infile=fopen("G:\\test.data","r"))==NULL)
{
cout<<"没有test.data这个文件,无法导入数据"<<endl;
exit(1);
}
for(i=0;i<Psize;i++)//数据集的大小
{
for(j=0;j<Length;j++)//每条数据集中的个数
{
fscanf(infile,"%lf",&data);
all_data[i].p[j]=data; //存入到all_data中去。
// cout<<data<<" ";
}
// cout<<endl;
}
fclose(infile);//关闭文件描述符
}
//检查数据是否相等
int Equal(int a[],int n,int b)
{
for(int i=0;i<n;i++)
if(a[i]==b) return 1;
return 0;
}
//随机初始化聚类质心(要检测聚类中心不能相同)
void Init_center()
{
int sum=0;
int rand_num;
int center[K];
//随机产生三个0~Psize的数
while(sum<K)
{
rand_num=rand()%Psize;//设定中心标号
if(!Equal(center,sum,rand_num))
{
center[sum++]=rand_num;
}
}
for(int i=0;i<K;i++)//中心数据放到center中
{
for(int j=0;j<Length;j++)
{
sample.clu_cent[i].p[j]=all_data[center[i]].p[j];//重新赋值
}
}
}
//欧几里得距离公式
double Euclidean_Distance(int a,int b)//a代表的是样本数据,b代表的是簇中心数据
{
double square=0;
for(int i=0;i<Length;i++)
{
square+=pow((all_data[a].p[i]-sample.clu_cent[b].p[i]),2);
}
/*
for(int i=0;i<n;i++)//n维向量
{
square+=(a[i]-b[i])*(a[i]-b[i]);
}
*/
return sqrt(square);
}
//计算Psize组数据到K个质心的欧几里得距离
void claculate_distance()
{
int i,j;
for(i=0;i<Psize;i++)
for(j=0;j<K;j++)
{
all_data[i].distance[j]=Euclidean_Distance(i,j);//传递的是向量的标号
}
}
//将数据进行聚类
void cluster()
{
double minV;
for(int i=0;i<K;i++) //初始化每个簇中心中的数据为0
sample.cluster_num[i]=0;
for(int i=0;i<Psize;i++)
{
int index=0;
minV=all_data[i].distance[0];
for(int j=1;j<K;j++)//筛选到簇心欧几里得最小的
{
if(all_data[i].distance[j]<minV)
{
minV=all_data[i].distance[j];
index=j;
}
}
//划分簇集:记录每个簇中样本的总个数
//sample.cluster_num[index]存储的是该类总的样本的当前总数
sample.cluster[index][sample.cluster_num[index]++]=i;
}
double tem=0;
//计算样本误差和
for(int i = 0; i < K; i++)
for(int j = 0; j < sample.cluster_num[i]; j++){
tem +=pow(all_data[sample.cluster[i][j]].distance[i],2);
}
sample.old_data = sample.data;
sample.data =tem;
}
//重新计算类中心,按照列进行计算
void new_center()
{
int i, j, n;
double tmp_sum;
for(i = 0; i < K; i++)//簇中心
for(j = 0; j < Length; j++)//向量维数
{
tmp_sum = 0;
for(n = 0; n < sample.cluster_num[i]; n++) //第i个簇的第j维数的所有数据和&&求平均值
{
//sample.cluster[i][n]存储的是样本的编号
tmp_sum += all_data[sample.cluster[i][n]].p[j];
}
//取平均数得到新的簇中心
sample.clu_cent[i].p[j] = tmp_sum / sample.cluster_num[i];
}
}
//输出实验结果
void output()
{
for(int i=0;i<K;i++)
{
cout<<"第"<<i<<"类为:"<<endl;
for(int k=0;k<sample.cluster_num[i];k++)//sample.cluster_num[i]记录的是该类中,样本量的个数
{
for(int j=0;j<Length;j++)//Length每条样本长度
{
//sample.cluster[i][k]记录样本标号
cout<<all_data[sample.cluster[i][k]].p[j]<<" ";
}
cout<<endl;
}
}
}
int main()
{
int iteration;
double differ = 1;
int flag = 0;
rand_data();//生成样本数据
input_data();//将样本输入读入内存
Init_center();//初始化类中心
iteration=0;//迭代标记,T=100,即迭代次数为100,可自己设定
while(1)
{
claculate_distance(); //计算欧几里德距离
cluster(); //根据距离聚类
differ = sample.old_data - sample.data; /* 判断条件 */
differ = fabs(differ);
if(differ<=End||iteration>T)
break;
new_center();//重新计算类中心
}
output(); /* 聚类后显示结果 */
return 0;
}