C++实现K均值

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

刀么克瑟拉莫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值