当前位置: 编程技术>c/c++/嵌入式
用C++实现DBSCAN聚类算法
来源: 互联网 发布时间:2014-10-15
本文导语: 这几天由于工作需要,对DBSCAN聚类算法进行了C++的实现。时间复杂度O(n^2),主要花在算每个点领域内的点上。算法很简单,现共享大家参考,也希望有更多交流。 数据点类型描述如下: 代码如下:#include using namespace std; const...
这几天由于工作需要,对DBSCAN聚类算法进行了C++的实现。时间复杂度O(n^2),主要花在算每个点领域内的点上。算法很简单,现共享大家参考,也希望有更多交流。
数据点类型描述如下:
#include
using namespace std;
const int DIME_NUM=2; //数据维度为2,全局常量
//数据点类型
class DataPoint
{
private:
unsigned long dpID; //数据点ID
double dimension[DIME_NUM]; //维度数据
long clusterId; //所属聚类ID
bool isKey; //是否核心对象
bool visited; //是否已访问
vector 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& GetArrivalPoints(); //GetArrivalPoints方法
};
这是实现:
#include "DataPoint.h"
//默认构造函数
DataPoint::DataPoint()
{
}
//构造函数
DataPoint::DataPoint(unsigned long dpID,double* dimension , bool isKey):isKey(isKey),dpID(dpID)
{
//传递每维的维度数据
for(int i=0; idimension[i]=dimension[i];
}
}
//设置维度数据
void DataPoint::SetDimension(double* dimension)
{
for(int i=0; idimension[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;
}
//GetClusterId方法
void DataPoint::SetClusterId( long clusterId )
{
this->clusterId = clusterId;
}
//GetArrivalPoints方法
vector& DataPoint::GetArrivalPoints()
{
return arrivalPoints;
}
DBSCAN算法类型描述:
#include
#include
using namespace std;
//聚类分析类型
class ClusterAnalysis
{
private:
vector 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(char* fileName, double radius, int minPTs); //初始化操作
bool DoDBSCANRecursive(); //DBSCAN递归算法
bool WriteToFile(char* fileName); //将聚类结果写入文件
};
聚类实现:
#include "ClusterAnalysis.h"
#include
#include
#include
/*
函数:聚类初始化操作
说明:将数据文件名,半径,领域最小数据个数信息写入聚类算法类,读取文件,把数据信息读入写进算法类数据集合中
参数:
char* fileName; //文件名
double radius; //半径
int minPTs; //领域最小数据个数
返回值: true; */
bool ClusterAnalysis::Init(char* fileName, double radius, int minPTs)
{
this->radius = radius; //设置半径
this->minPTs = minPTs; //设置领域最小数据个数
this->dimNum = DIME_NUM; //设置数据维度
ifstream ifs(fileName); //打开文件
if (! ifs.is_open()) //若文件已经被打开,报错误信息
{
cout tempDimData[j];
}
tempDP.SetDimension(tempDimData); //将维度信息存入数据点对象内
//char date[20]="";
//char time[20]="";
////double type; //无用信息
//ifs >> date;
//ifs >> time; //无用信息读入
tempDP.SetDpId(i); //将数据点对象ID设置为i
tempDP.SetVisited(false); //数据点对象isVisited设置为false
tempDP.SetClusterId(-1); //设置默认簇ID为-1
dadaSets.push_back(tempDP); //将对象压入数据集合容器
i++; //计数+1
}
ifs.close(); //关闭文件流
dataNum =i; //设置数据对象集合大小为i
for(unsigned long i=0; i
Base64编码原理详解及c++编码解码实现
我实现了个J2EE技术的服务器,支持TCP、UDP和数据库,由于性能的原因,需要改为C或C++实现,我是C、C++新手,我该如何入手呢?看什么样的
c++实现MD5算法代码示例
java 与 C++ 实现后绑定的方法
c++通用模板类(template class)定义实现详细介绍
Qt实现的C++框架 qtioccontainer
用C或C++实现主存的分配与回收
在linux系统上,如何用C++实现获取和设置系统时间?
文本压缩算法C++实现 Golden Huffman
C++标准库实现 libc++
C++的XMLRPC实现 XMLRPC++
Java/JavaScript API 的 C++ 实现 libj
c++ 连接两个字符串实现代码 实现类似strcat功能
c++在unix中如何实现CString的方法?或者说有没有替换CString的类?
请问:java中如何实现C++中的sizeof()方法?
用C或C++编程,模拟可变分区存储管理且首次适应的算法实现存储器的分配与回收
vim中如何实现c++代码编写的自动格式化和语法高亮的功能?
C++实现CreatThread函数主线程与工作线程交互的方法
请教为什么在C++编译通过并实现的程序,在linux下就会出错
linux下c++怎样实现回调(CALLBACK)函数?
数据点类型描述如下:
代码如下:
#include
using namespace std;
const int DIME_NUM=2; //数据维度为2,全局常量
//数据点类型
class DataPoint
{
private:
unsigned long dpID; //数据点ID
double dimension[DIME_NUM]; //维度数据
long clusterId; //所属聚类ID
bool isKey; //是否核心对象
bool visited; //是否已访问
vector 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& GetArrivalPoints(); //GetArrivalPoints方法
};
这是实现:
代码如下:
#include "DataPoint.h"
//默认构造函数
DataPoint::DataPoint()
{
}
//构造函数
DataPoint::DataPoint(unsigned long dpID,double* dimension , bool isKey):isKey(isKey),dpID(dpID)
{
//传递每维的维度数据
for(int i=0; idimension[i]=dimension[i];
}
}
//设置维度数据
void DataPoint::SetDimension(double* dimension)
{
for(int i=0; idimension[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;
}
//GetClusterId方法
void DataPoint::SetClusterId( long clusterId )
{
this->clusterId = clusterId;
}
//GetArrivalPoints方法
vector& DataPoint::GetArrivalPoints()
{
return arrivalPoints;
}
DBSCAN算法类型描述:
代码如下:
#include
#include
using namespace std;
//聚类分析类型
class ClusterAnalysis
{
private:
vector 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(char* fileName, double radius, int minPTs); //初始化操作
bool DoDBSCANRecursive(); //DBSCAN递归算法
bool WriteToFile(char* fileName); //将聚类结果写入文件
};
聚类实现:
代码如下:
#include "ClusterAnalysis.h"
#include
#include
#include
/*
函数:聚类初始化操作
说明:将数据文件名,半径,领域最小数据个数信息写入聚类算法类,读取文件,把数据信息读入写进算法类数据集合中
参数:
char* fileName; //文件名
double radius; //半径
int minPTs; //领域最小数据个数
返回值: true; */
bool ClusterAnalysis::Init(char* fileName, double radius, int minPTs)
{
this->radius = radius; //设置半径
this->minPTs = minPTs; //设置领域最小数据个数
this->dimNum = DIME_NUM; //设置数据维度
ifstream ifs(fileName); //打开文件
if (! ifs.is_open()) //若文件已经被打开,报错误信息
{
cout tempDimData[j];
}
tempDP.SetDimension(tempDimData); //将维度信息存入数据点对象内
//char date[20]="";
//char time[20]="";
////double type; //无用信息
//ifs >> date;
//ifs >> time; //无用信息读入
tempDP.SetDpId(i); //将数据点对象ID设置为i
tempDP.SetVisited(false); //数据点对象isVisited设置为false
tempDP.SetClusterId(-1); //设置默认簇ID为-1
dadaSets.push_back(tempDP); //将对象压入数据集合容器
i++; //计数+1
}
ifs.close(); //关闭文件流
dataNum =i; //设置数据对象集合大小为i
for(unsigned long i=0; i