系统聚类(hierarchical cluster method)算法简述
- 每个独立点作为一个类
- 对每个类两两求距离
- 将距离最近的两个类作为一个新的类
- 重复2-3步直到达到分出目标的k个类为止
算法实现
数据构造及应用场景:构造n个善意结点(数据偏差很小的结点)和nn-n个恶意结点(恶意结点)。欲使用系统聚类的方式将恶意结点和善意结点分离开来
代码实现
#include<iostream>
#include<bits/stdc++.h>
#define random(x) (rand()%x)
using namespace std;
class A {
public:
int no;
double val;
A(int n, double v):no(n), val(v){}
};
class Cluster{
public:
vector<A> clu;
double gravity;//重心法计算距离
double sum;
void addNewMember(A m){
//加入一个元素以后更新这个类
sum += m.val;
clu.push_back(m);
gravity = sum / clu.size();
}
Cluster(A m){
sum = m.val;
clu.push_back(m);
gravity = m.val;
}
Cluster(){
sum = 0;//注意对sum的初始化
}
};
vector<Cluster> v;
void hcm(int k){
//hierarchical cluster method 系统聚类:分为k类
while(v.size() > k ){//类数没达到目标,继续分类
int no1, no2;
double minDis = DBL_MAX;
for(int i = 0; i < v.size(); i++){
for(int j = i+1; j < v.size(); j++){
if(abs(v[i].gravity-v[j].gravity) < minDis){//求距离最小的两个类
minDis = abs(v[i].gravity-v[j].gravity);
no1 = i;
no2 = j;
}
}
}
Cluster newc;//创建一个新类来合并距离最近的两个类
for(int i = 0; i < v[no1].clu.size(); i++){
newc.addNewMember(v[no1].clu[i]);
}
for(int j = 0; j < v[no2].clu.size(); j++){
newc.addNewMember(v[no2].clu[j]);
}
v.erase(v.begin() + no2);//删掉距离最近的两个类
v.erase(v.begin() + no1);
v.push_back(newc);//插入新类
}
}
int main(){
int n = 10;//善意结点数
int nn = 12;//总结点数
srand((unsigned)clock());
int seed = random(50);
srand((unsigned)clock());
for(int i = 0; i < n; i++){
A a(i, seed + (random(20) - 9) / 10.0);
v.push_back(Cluster(a));
}
for(int i = n; i < nn; i++){
A a(i, seed + (random(200) - 99) / 10.0);
v.push_back(Cluster(a));
}
hcm(3);
for(int i = 0; i < v.size(); i++){
cout<<"第"<<i<<"类:";
for(int j = 0; j < v[i].clu.size();j++)
cout<<v[i].clu[j].no<<' ';
cout<<endl;
}
cout<<"真实的恶意结点:"<<n<<'~'<<nn-1<<endl;
return 0;
}
复杂度分析
感觉这个 k k k分类的时间复杂度是 O ( m n 2 ) O(mn^2) O(mn2)级别的,其中 m = n − k m=n-k m=n−k