实验内容
- 扁平聚类:随机生成30个2维向量,将他们聚成3个簇,然后在平面上表示出来。
#include<iostream>
#include<vector>
#include<math.h>
#include<time.h>
using namespace std;
struct Point {
int x;
int y;
};
//质点与质心距离
double distance(Point point_1, Point point_2) {
return sqrt((point_1.x - point_2.x) * (point_1.x - point_2.x) + (point_1.y - point_2.y) * (point_1.y - point_2.y));
}
//计算当前簇集的质心
Point getmycenter(vector<int> cluster[3], vector<Point>& point, int i,Point mycenter[]) {
Point t;
double num = cluster[i].size();
double centerX = 0, centerY = 0;
vector<int>::iterator it = cluster[i].begin();
for (; it != cluster[i].end(); it++) {
centerX += point[*it].x;
centerY += point[*it].y;
}
if (num == 0)
return mycenter[i];
t.x = centerX / num;//计算重心
t.y = centerY / num;
return t;
}
//显示
void printscreen(Point mycenter[3], vector<int> cluster[], vector<Point>& point) {
int a[51][51] = {0};
int z[4] = {1,2,3,4};
for (int m = 0; m < 3; m++) {
vector<int>::iterator it = cluster[m].begin();
for (; it != cluster[m].end(); it++) {
a[point[*it].x][point[*it].y] = z[m];
}
}
for (int i = 0; i < 3; i++) {
a[mycenter[i].x][mycenter[i].y] = 4;//k个质心
}
for (int i = 0; i < 80; i++)
cout << "-"; cout << "x";
cout << endl;
for (int i = 0; i < 51; i++) {
cout << "|";
for (int j = 0; j < 51; j++) {
if (a[i][j] ==1)
cout << "*" ;
else if (a[i][j] == 2)
cout << "@";
else if (a[i][j] == 3)
cout << "#";
else if (a[i][j] == 4)
cout << "&";
else
cout <<" ";
}
cout << endl;
}
}
void kmeans(vector<Point>& point, int n, int k) {
vector<int> cluster[3];//容器组,一个容器存放一个簇的索引号
Point mycenter[3];//存放k个质心的数组
for (int i = 0; i < k; i++) {
mycenter[i].x = point[i].x;//用前三个元素初始化k个质心
mycenter[i].y = point[i].y;
}
//第一次计算各个质点到k个质心的距离,并得到第一次分配的容器组
for (int i = 0; i < n; i++) {
double _distance = distance(mycenter[0], point[i]);
int label = 0;
double num;
for (int j = 0; j < k; j++) {
num = distance(mycenter[j], point[i]);
if (num < _distance){
label = j;//获取其距离质心最近的序号
_distance = num;
}
}
cluster[label].push_back(i);//将第i个向量放入与其距离质心最近所在的簇中
}
for (int i = 0; i < 200; i++) {
//计算新质心
for (int i = 0; i < 3; i++) {
mycenter[i] = getmycenter(cluster, point, i,mycenter);
}
//清空旧的容器
for (int i = 0; i < k; i++)
cluster[i].clear();
//构建新的容器
for (int i = 0; i < n; i++) {
double _distance = distance(mycenter[0], point[i]);
int label = 0;
for (int j = 0; j < k; j++) {
if (distance(mycenter[j], point[i]) < _distance)
label = j;//获取其距离质心最近的序号
}
cluster[label].push_back(i);//将第i个向量放入与其距离质心最近所在的簇中
}
}
printscreen(mycenter,cluster, point);
}
void input(vector<Point>& point, int n) {
Point _point[30];
srand((unsigned)time(NULL));//time()用系统时间初始化种。为rand()生成不同的随机种子。
cout << "随机生成的" << n << "个数据:" << endl;
for (int i = 0; i < 30; i++)
{
_point[i].x = rand() % 50 +1;//生成1~50随机数
_point[i].y = rand() % 50 +1;
point.push_back(_point[i]);
cout << "第" << i + 1 << "个向量为:" << point[i].x << "\t\t" << point[i].y << endl;
}
}
int main() {
vector<Point> point;//质点
int n, k;
//cout << "请输入向量个数以及簇的个数" << endl;
//cin >> n >> k;
n = 30; k = 3;
input(point,n);
kmeans(point,n,k);
return 0;
}