DBSCAN聚类算法进行了C++的实现,时间复杂度为O(n^2)。

1、数据点类型描述如下(DataPoint.h)

#include <vector>
using namespace std;
const int DIME_NUM=2;        //数据维度为2,全局常量//数据点类型
class DataPoint
{
private:unsigned long dpID;                //数据点IDdouble dimension[DIME_NUM];        //维度数据long clusterId;                    //所属聚类IDbool isKey;                        //是否核心对象bool visited;                    //是否已访问vector<unsigned long> arrivalPoints;    //领域数据点id列表public:DataPoint();                                                    //默认构造函数DataPoint(unsigned long dpID,double* dimension , bool isKey);    //构造函数unsigned long GetDpId();                //GetDpId方法void SetDpId(unsigned long dpID);        //SetDpId方法double* GetDimension();                    //GetDimension方法void SetDimension(double* dimension);    //SetDimension方法bool IsKey();                            //GetIsKey方法void SetKey(bool isKey);                //SetKey方法bool isVisited();                        //GetIsVisited方法void SetVisited(bool visited);            //SetIsVisited方法long GetClusterId();                    //GetClusterId方法void SetClusterId(long classId);        //SetClusterId方法vector<unsigned long>& GetArrivalPoints();    //GetArrivalPoints方法};

2、对应实现(DataPoint.cpp)

#include "DataPoint.h"//默认构造函数DataPoint::DataPoint(){}//构造函数DataPoint::DataPoint(unsigned long dpID,double* dimension , bool isKey):isKey(isKey),dpID(dpID){//传递每维的维度数据for(int i=0; i<DIME_NUM;i++){this->dimension[i]=dimension[i];}}//设置维度数据void DataPoint::SetDimension(double* dimension){for(int i=0; i<DIME_NUM;i++){this->dimension[i]=dimension[i];}}//获取维度数据double* DataPoint::GetDimension(){return this->dimension;}//获取是否为核心对象bool DataPoint::IsKey(){return this->isKey;}//设置核心对象标志void DataPoint::SetKey(bool isKey){this->isKey = isKey;}//获取DpId方法unsigned long DataPoint::GetDpId(){return this->dpID;}//设置DpId方法void DataPoint::SetDpId(unsigned long dpID){this->dpID = dpID;}//GetIsVisited方法bool DataPoint::isVisited(){return this->visited;}//SetIsVisited方法void DataPoint::SetVisited( bool visited ){this->visited = visited;}//GetClusterId方法long DataPoint::GetClusterId(){return this->clusterId;}//SetClusterId方法void DataPoint::SetClusterId( long clusterId ){this->clusterId = clusterId;}//GetArrivalPoints方法vector<unsigned long>& DataPoint::GetArrivalPoints(){return arrivalPoints;}

3、DBSCAN算法类型描述(ClusterAnalysis.h)

#include <iostream>
#include <cmath>
#include "DataPoint.h"
#include<QVector>using namespace std;//聚类分析类型class ClusterAnalysis{private:vector<DataPoint> dadaSets;        //数据集合unsigned int dimNum;            //维度double radius;                    //半径unsigned int dataNum;            //数据数量unsigned int minPTs;            //邻域最小数据个数double GetDistance(DataPoint& dp1, DataPoint& dp2);                    //距离函数void SetArrivalPoints(DataPoint& dp);                                //设置数据点的领域点列表void KeyPointCluster( unsigned long i, unsigned long clusterId );    //对数据点领域内的点执行聚类操作public:ClusterAnalysis(){}                    //默认构造函数bool Init(QVector<QVector<QString>> Data, double radius, int minPTs);    //初始化操作unsigned long DoDBSCANRecursive();            //DBSCAN递归算法bool WriteToFile(char* fileName);    //将聚类结果写入文件bool ClusterAnalysis::GetScope(Scope* scope, QVector<QVector<QString>> Data);   //将已经过聚类算法处理的数据集合形成坐标范围};

4、算法实现(ClusterAnalysis.cpp)

#include "ClusterAnalysis.h"
#include <fstream>
#include <iosfwd>
#include <math.h>/*函数:聚类初始化操作
说明:将数据文件名,半径,领域最小数据个数信息写入聚类算法类,读取文件,把数据信息读入写进算法类数据集合中
参数:
QVector<QVector<QString>> Data;    //数据
double radius;    //半径
int minPTs;        //领域最小数据个数
返回值: true;    */
bool ClusterAnalysis::Init(QVector<QVector<QString>> Data, double radius, int minPTs)
{this->radius = radius;        //设置半径this->minPTs = minPTs;        //设置领域最小数据个数this->dimNum = DIME_NUM;    //设置数据维度unsigned long i=0;            //数据个数统计//从Data读取POI信息,将POI信息写入POI列表中for (int k = 0; k < Data.size(); k++){DataPoint tempDP;                //临时数据点对象double tempDimData[DIME_NUM];    //临时数据点维度信息for(int j=0; j<DIME_NUM; j++)    //读Data,读取每一维数据{tempDimData[j] = Data.at(k).at(j).toDouble();}tempDP.SetDimension(tempDimData);    //将维度信息存入数据点对象内//char date[20]="";//char time[20]="";double type;    //无用信息//ifs >> date;//ifs >> time;    //无用信息读入tempDP.SetDpId(i);                    //将数据点对象ID设置为itempDP.SetVisited(false);            //数据点对象isVisited设置为falsetempDP.SetClusterId(-100);            //设置默认簇ID为-1dadaSets.push_back(tempDP);            //将对象压入数据集合容器i++;        //计数+1}dataNum =i;            //设置数据对象集合大小为ifor(unsigned long i=0; i<dataNum;i++){SetArrivalPoints(dadaSets[i]);            //计算数据点领域内对象}return true;    //返回}/*函数:将已经过聚类算法处理的数据集合写回文件说明:将已经过聚类结果写回文件
参数:
char* fileName;    //要写入的文件名
返回值: true    */
bool ClusterAnalysis::WriteToFile(char* fileName )
{ofstream of1(fileName);                                //初始化文件输出流for(unsigned long i=0; i<dataNum;i++)                //对处理过的每个数据点写入文件{for(int d=0; d<DIME_NUM ; d++)                    //将维度信息写入文件of1<<dadaSets[i].GetDimension()[d]<<'\t';of1 << dadaSets[i].GetClusterId() <<endl;        //将所属簇ID写入文件}of1.close();    //关闭输出文件流return true;    //返回}/*函数:设置数据点的领域点列表
说明:设置数据点的领域点列表
参数:返回值: true;    */void ClusterAnalysis::SetArrivalPoints(DataPoint& dp){for(unsigned long i=0; i<dataNum; i++)                //对每个数据点执行{double distance =GetDistance(dadaSets[i], dp);    //获取与特定点之间的距离if(distance <= radius && i!=dp.GetDpId())        //若距离小于半径,并且特定点的id与dp的id不同执行dp.GetArrivalPoints().push_back(i);            //将特定点id压力dp的领域列表中}if(dp.GetArrivalPoints().size() >= minPTs)            //若dp领域内数据点数据量> minPTs执行{dp.SetKey(true);    //将dp核心对象标志位设为truereturn;                //返回}dp.SetKey(false);    //若非核心对象,则将dp核心对象标志位设为false}/*函数:执行聚类操作说明:执行聚类操作参数:返回值: true;    */unsigned long ClusterAnalysis::DoDBSCANRecursive(){unsigned long clusterId=0;                        //聚类id计数,初始化为0for(unsigned long i=0; i<dataNum;i++)            //对每一个数据点执行{DataPoint& dp=dadaSets[i];                    //取到第i个数据点对象if(!dp.isVisited() && dp.IsKey())            //若对象没被访问过,并且是核心对象执行{dp.SetClusterId(clusterId);                //设置该对象所属簇ID为clusterIddp.SetVisited(true);                    //设置该对象已被访问过KeyPointCluster(i,clusterId);            //对该对象领域内点进行聚类clusterId++;                            //clusterId自增1}//cout << "孤立点\T" << i << endl;}//    cout <<"共聚类" <<clusterId<<"个"<< endl;        //算法完成后,输出聚类个数return clusterId;    //返回}/*函数:对数据点领域内的点执行聚类操作说明:采用递归的方法,深度优先聚类数据参数:unsigned long dpID;            //数据点idunsigned long clusterId;    //数据点所属簇id返回值: void;    */void ClusterAnalysis::KeyPointCluster(unsigned long dpID, unsigned long clusterId ){DataPoint& srcDp = dadaSets[dpID];        //获取数据点对象if(!srcDp.IsKey())    return;vector<unsigned long>& arrvalPoints = srcDp.GetArrivalPoints();        //获取对象领域内点ID列表for(unsigned long i=0; i<arrvalPoints.size(); i++){DataPoint& desDp = dadaSets[arrvalPoints[i]];    //获取领域内点数据点if(!desDp.isVisited())                            //若该对象没有被访问过执行{//cout << "数据点\t"<< desDp.GetDpId()<<"聚类ID为\t" <<clusterId << endl;desDp.SetClusterId(clusterId);        //设置该对象所属簇的ID为clusterId,即将该对象吸入簇中desDp.SetVisited(true);                //设置该对象已被访问if(desDp.IsKey())                    //若该对象是核心对象{KeyPointCluster(desDp.GetDpId(),clusterId);    //递归地对该领域点数据的领域内的点执行聚类操作,采用深度优先方法}}}}//两数据点之间距离/*函数:获取两数据点之间距离说明:获取两数据点之间的欧式距离参数:DataPoint& dp1;        //数据点1DataPoint& dp2;        //数据点2返回值: double;    //两点之间的距离        */double ClusterAnalysis::GetDistance(DataPoint& dp1, DataPoint& dp2){double distance =0;        //初始化距离为0for(int i=0; i<DIME_NUM;i++)    //对数据每一维数据执行{distance += pow(dp1.GetDimension()[i] - dp2.GetDimension()[i],2);    //距离+每一维差的平方}return pow(distance,0.5);        //开方并返回距离}/*函数:将已经过聚类算法处理的数据集合形成坐标范围参数:Scope* scopee;    //要写入的坐标范围返回值: true    */bool ClusterAnalysis::GetScope(Scope* scope, QVector<QVector<QString>> Data){for (unsigned long i = 0; i<dataNum; i++)                //对处理过的每个数据点写入文件{long clusterId = dadaSets[i].GetClusterId();if (clusterId >= 0) {if (scope[clusterId].flag == false) {scope[clusterId].lon_max = dadaSets[i].GetDimension()[0];scope[clusterId].lon_min = dadaSets[i].GetDimension()[0];scope[clusterId].lat_max = dadaSets[i].GetDimension()[1];scope[clusterId].lat_min = dadaSets[i].GetDimension()[1];scope[clusterId].flag = true;}else {if (dadaSets[i].GetDimension()[0] > scope[clusterId].lon_max) {scope[clusterId].lon_max = dadaSets[i].GetDimension()[0];}if (dadaSets[i].GetDimension()[0] < scope[clusterId].lon_min) {scope[clusterId].lon_min = dadaSets[i].GetDimension()[0];}if (dadaSets[i].GetDimension()[1] > scope[clusterId].lat_max) {scope[clusterId].lat_max = dadaSets[i].GetDimension()[1];}if (dadaSets[i].GetDimension()[1] < scope[clusterId].lat_min) {scope[clusterId].lat_min = dadaSets[i].GetDimension()[1];}}int num = (scope[clusterId].num);scope[clusterId].Datas[num] = i;scope[clusterId].num++;}}return true;    //返回}

5、算法调用

首先需要对QVector<QVector<QString>> Data 源数据进行附值。

    #include "ClusterAnalysis.h"#include <cstdio>using namespace std;int main(){QVector<QVector<QString>> Data;            //首先给Data数据赋值(如经纬度数据)。ClusterAnalysis myClusterAnalysis;                        //聚类算法对象声明myClusterAnalysis.Init(Data, 3, 1);        //算法初始化操作,指定半径为3,领域内最小数据点个数为1,(在程序中已指定数据维度为2)unsigned long clusterId = myClusterAnalysis.DoDBSCANRecursive();                    //执行聚类算法                                                  Scope* scope = new Scope[clusterId + 1];myClusterAnalysis.GetScope(scope, Data);return 0;            //返回}

基于C++实现DBSCAN聚类算法相关推荐

  1. 基于GPU的K-Means聚类算法

    聚类是信息检索.数据挖掘中的一类重要技术,是分析数据并从中发现有用信息的一种有效手段.它将数据对象分组成为多个类或簇,使得在同一个簇中的对象之间具有较高的相似度,而不同簇中的对象差别很大.作为统计学的 ...

  2. dbscan聚类算法matlab_密度聚类DBSCAN、HDBSCAN(转)

    # 密度聚类DBSCAN.HDBSCAN DBSCAN DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声 ...

  3. dbscan聚类算法_一种视频人群流的轨迹聚类方法

    tags: KLT光流法,K-means聚类算法,DBSCAN聚类算法 方法简介 运动轨迹是一种在视频场景中捕捉复杂时间动态的有效方法.因此,我们将人流分割问题转化为一个轨迹提取和聚类任务.该方法分为 ...

  4. DBSCAN聚类算法原理及图解

    DBSCAN(Density-Based Spatial Clustering of Applications with Noise,具有噪声的基于密度的聚类方法)是一种很典型的密度聚类算法,和K-M ...

  5. K-means与DBSCAN聚类算法

    K-means与DBSCAN聚类算法 前言:目前数据聚类方法大体上可以分为划分式聚类方法(Partition-based Methods).基于密度的聚类方法(Density-based method ...

  6. 毫米波雷达点云 DBSCAN聚类算法

    毫米雷达点云 DBSCAN聚类算法 聚类的目的 聚类算法分类 原型聚类 层次聚类 密度聚类 DBSCAN聚类算法原理 相关定义 算法流程以及伪代码 DBSCAN算法优缺点 DBSCAN参数选择 聚类衡 ...

  7. dbscan算法_如何掌握用于机器学习的流行DBSCAN聚类算法

    总览 DBSCAN聚类是一种针对无监督学习问题而被低估但非常有用的聚类算法 了解DBSCAN集群如何工作,为什么要学习以及如何在Python中实现DBSCAN集群 介绍 掌握无监督学习为数据科学家开辟 ...

  8. DBSCAN聚类算法——机器学习(理论+图解+python代码)

    一.前言 二.DBSCAN聚类算法 三.参数选择 四.DBSCAN算法迭代可视化展示 五.常用的评估方法:轮廓系数 六.用Python实现DBSCAN聚类算法 一.前言 去年学聚类算法的R语言的时候, ...

  9. dbscan算法c语言实现,用C++实现DBSCAN聚类算法

    这几天由于工作需要,对DBSCAN聚类算法进行了C++的实现.时间复杂度O(n^2),主要花在算每个点领域内的点上.算法很简单,现共享大家参考,也希望有更多交流. 数据点类型描述如下: 复制代码 代码 ...

  10. WKmeans一种基于特征权重的聚类算法

    1 引例 在前面两篇文章中,我们首先介绍了KmeansKmeansKmeans聚类算法的原理:然后又介绍了一种基于KmeansKmeansKmeans进行改进的Kmeans++Kmeans++Kmea ...

最新文章

  1. python代码基础题-Python初学者福利 完整试题附答案 干货(收藏篇)
  2. IDEA报错Web server failed to start. Port 8080 was already in use的解决方法
  3. 几位阿里朋友重写的Java并发编程,牛逼了
  4. SpringBoot使用@Cacheable实现最简单的Redis缓存
  5. 一个Demo学会用Android兼容包新控件
  6. 从数组到 HashMap 之算法解释
  7. RedHat Linux 加入域
  8. C#中网络编程异步操作方法与 粘包和分包问题
  9. java gson 解析json字符串_JSON 之GSON 解析
  10. 【C++】【GADL】读取栅格数据获取信息
  11. Notepad工具json格式转换
  12. SQL SERVER 修改字段长度
  13. 美团2015年校园招聘部分笔试题
  14. Springboot整合ES8(Java API Client)
  15. 应用场景是什么?怎样判断、描述一个产品的应用场景?
  16. Instagram 账号被封如何申诉拿回账号?ins账号解封经验分享
  17. 当代大学生的生活痛点
  18. John Ripper的模式和配置
  19. 南琼考试系统服务器怎么填,南琼考试系统N5
  20. 使用Mybatis联表查询的几种方式

热门文章

  1. 开发者需要什么样的技术社区?
  2. 使用html查看dicom,LEADTOOLS构建HTML5 DICOM/PACS查看器(二)
  3. Kindle 文档生成工具
  4. 【干货满满】初级银行从业考试《个人理财》重点梳理
  5. 戴尔计算机更新程序,戴尔电脑怎么关闭自动更新系统
  6. 实名认证失败_公安实名认证失败是什么原因
  7. 移动创业者,这么多免费资源,你不要?
  8. 中国移动何时成为“移动信息专家”
  9. 年会抽奖 - 牛客网题解
  10. 【敏捷开发模式的介绍】