K-means算法的c++代码实现

1.K-means算法步骤

  1. 从数据中选择k个对象作为初始聚类中心;
  2. 计算每个聚类对象到聚类中心的距离来划分(被划分到距离最近的那个中心点的簇里);
  3. 再次计算每个聚类中心
  4. 重新开始步骤2和步骤3,进行迭代直到满足结束条件(当前迭代次数达到指定迭代次数、中心点坐标距离变化量低于指定值、每个簇里的元素或者元素数量不再发生变化等,根据不同要求确定不同结束条件)
  5. 确定最优的聚类中心

2.相关问题

1.计算距离

K-means算法采用的是欧氏距离:各维度差的平方和。
D i s t ( X , Y ) = ∑ i = 1 n ( x i − y i ) 2 Dist(X,Y)=\sqrt{\sum_{i=1}^{n}(x_{i}-y_{i})^{2}} Dist(X,Y)=i=1n(xiyi)2

2. 如何计算中心点坐标

计算的公式和重心坐标公式是一致的,所有点每个维度的均值
c e n t e r ( ∑ i = 1 n P 1 i n , ∑ i = 1 n P 2 i n , . . . , ∑ i = 1 n P m i n ) center(\frac{\sum_{i=1}^{n}P1_{i}}{n},\frac{\sum_{i=1}^{n}P2_{i}}{n},...,\frac{\sum_{i=1}^{n}Pm_{i}}{n}) center(ni=1nP1i,ni=1nP2i,...,ni=1nPmi)

具体代码实现

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define endl '\n'
struct Point {//存储点 
	vector<double> pos;//存储各维度值 
	int aff=-1;//所属中心点下标
} p[100];
int n,m,k,temp;//n:数据点数,m:点的维度,k:中心点数 
vector<Point> center;//中心点坐标
double getdis(const Point &p1,const Point &p2) {//获取两点距离
	double result=0;
	for(int i=0; i<m; i++) {
		result+=(p1.pos[i]-p2.pos[i])*(p1.pos[i]-p2.pos[i]);
	}
	return result;
}
void K_means() {
	bool changed=true;
	while(changed) {
		changed=false;
		for(int i=1; i<=n; i++) {//聚类
			double mins=INT_MAX;
			int t=0;
			for(int j=0; j<center.size(); j++) {//遍历每一个中心点,找到离该点最近的那个中心点
				if(getdis(p[i],center[j])<mins) {
					t=j;
					mins=getdis(p[i],center[j]);
				}
			}
			if(p[i].aff!=t) {//如果该点的所属改变了,则说明要继续聚类
				p[i].aff=t;
				changed=true;
			}
		}
		for(int t=0; t<k; t++) {//计算每一个簇的中心点,并更新中心点坐标
			vector<double> pos(m,0);
			int cnt=0;
			for(int i=1; i<=n; i++) {
				if(p[i].aff==t) {
					cnt++;
					for(int j=0; j<m; j++) {
						pos[j]+=p[i].pos[j];
					}
				}
			}
			for(int j=0; j<m; j++) {
				pos[j]/=cnt;
			}
			center[t].pos=pos;
		}
	}
}
void output(int index) {//输出各个簇内点
	bool flag=false;
	for(int i=1; i<=n; i++) {
		if(p[i].aff==index) {
			if(flag)cout<<",";
			flag=true;
			cout<<i;
		}
	}
	cout<<endl;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m>>k;
	for(int i=1; i<=n; i++) {//输入数据点坐标 
		for(int j=0; j<m; j++) {
			cin>>temp;
			p[i].pos.push_back(temp);
		}
	}
	for(int i=0; i<k; i++) {//输入中心点坐标 
		cin>>temp;
		center.push_back(p[temp]);
	} 
	K_means();//执行K_means算法 
	for(int i=0; i<k; i++) {//输出 
		cout<<"cluster"<<i+1<<":";
		output(i);
	}
	return 0;
}
  • 26
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值