一维系统聚类c++实现

更详细的系统聚类说明

系统聚类(hierarchical cluster method)算法简述

  1. 每个独立点作为一个类
  2. 对每个类两两求距离
  3. 将距离最近的两个类作为一个新的类
  4. 重复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=nk

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值