#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <fstream>
#define M 19
#define N 2
#define K 2
using namespace std;
double data[M][N],oldcenter[K][N],newcenter[K][N];
//判断样本所属聚类:a是聚类中心数组,b是样本,m和n分别为k和维数,返回值为所属类
int judge(double *a,double b[],int m,int n){
double min = 0;
int ans = 0;
for(int j = 0; j < n; j++)
min += (a[j]-b[j])*(a[j]-b[j]);
for(int i = 1; i < m; i++){
double sum = 0;
for(int j = 0; j < n;j++)
sum += (b[j]-a[i*n+j])*(b[j]-a[i*n+j]);
if(min > sum){
min = sum;
ans = i;
}
}
return ans;
}
//计算新的聚类中心:k为聚类序号,r为属于聚类k的样本号数组,c为样本个数
void newCal(int k,int r[],int c){
for(int j=0; j<N; j++){
double sum = 0;
for(int i = 0; i <c; i++)
sum += data[r[i]][j];
newcenter[k][j] = sum/c;
}
}
//判断新旧聚类中心是否相等
bool equel(){
for(int i = 0; i < K; i++){
double sum = 0;
for(int j = 0; j < N;j++)
sum+=(oldcenter[i][j]-newcenter[i][j])*(oldcenter[i][j]-newcenter[i][j]);
if(sum > 0)
return false;
}
return true;
}
void k_means(){
srand((int)time(0)); //随机产生初始聚类中心
int randd[K];
for(int i = 0; i < K;i++){
randd[i] = rand()%M;
for(int j = 0; j < N; j++)
oldcenter[i][j] = data[randd[i]][j];
}
while(1){
int record[K][M]={0},cnt[K]={0};
for(int i = 0; i < M; i++){ //判断每个样本所属类别,并记录各类别的样本数
int ans = judge((double *)oldcenter,data[i],K,N);
record[ans][cnt[ans]++] = i;
}
for(int i = 0; i < K; i++)
newCal(i,record[i],cnt[i]);
if(equel()){
for(int i = 0; i < K; i++){
cout << i << "#\n";
for(int j = 0; j < cnt[i];j++){
cout << "(";
for(int dim = 0; dim < N-1; dim++)
cout << data[record[i][j]][dim] << ",";
cout << data[record[i][j]][N-1] << ") ";
}
cout << endl;
}
//ofstream output; //聚类结果写入txt文件
//output.open("res.txt");
//for(int i = 0; i < K; i++){
// output << i << "#\n";
// for(int j = 0; j < cnt[i];j++){
// output << "(";
// for(int dim = 0; dim < N-1; dim++)
// output << data[record[i][j]][dim] << ",";
// output << data[record[i][j]][N-1] << ")";
// }
// output << endl;
//}
//output.close();
break;
}
for(int i = 0; i < K;i++) //未到达终止条件,将新中心赋给旧中心
for(int j = 0; j < N;j++)
oldcenter[i][j]=newcenter[i][j];
}
}
int main()
{
ifstream input;
input.open("data.txt");
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
input >> data[i][j];
k_means();
system("PAUSE");
input.close();
return 0;
}
C++实现K均值
最新推荐文章于 2023-11-24 21:34:08 发布