亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

C++實現DBSCAN聚類的算法介紹

2020-02-24 14:27:15
字體:
來源:轉載
供稿:網友

DBSCAN聚類基于高密度連通區域聚類算法,它可以將高密度區域劃分為簇,并在噪聲數據中找到任意形狀的簇,下面就跟著武林技術頻道的步伐來了解C++實現DBSCAN聚類的算法介紹吧。
?數據點類型描述如下:

?

#include <vector>

?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<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方法
?};


這是實現:

?

?

?


#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;
?}

?//GetClusterId方法
?void DataPoint::SetClusterId( long clusterId )
?{
???? this->clusterId = clusterId;
?}

?//GetArrivalPoints方法
?vector<unsigned long>& DataPoint::GetArrivalPoints()
?{
???? return arrivalPoints;
?}


DBSCAN算法類型描述:

?

?

?


#include <iostream>
?#include <cmath>

?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(char* fileName, double radius, int minPTs);??? //初始化操作
???? bool DoDBSCANRecursive();??????????? //DBSCAN遞歸算法
???? bool WriteToFile(char* fileName);??? //將聚類結果寫入文件
?};


?聚類實現:

?

?

?


#include "ClusterAnalysis.h"
?#include <fstream>
?#include <iosfwd>
?#include <math.h>

?/*
?函數:聚類初始化操作
?說明:將數據文件名,半徑,領域最小數據個數信息寫入聚類算法類,讀取文件,把數據信息讀入寫進算法類數據集合中
?參數:
?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 << "Error opening file";??? //輸出錯誤信息
???????? exit (-1);??????????????????????? //程序退出
???? }

???? unsigned long i=0;??????????? //數據個數統計
???? while (! ifs.eof() )??????????????? //從文件中讀取POI信息,將POI信息寫入POI列表中
???? {
???????? DataPoint tempDP;??????????????? //臨時數據點對象
???????? double tempDimData[DIME_NUM];??? //臨時數據點維度信息
???????? for(int j=0; j<DIME_NUM; j++)??? //讀文件,讀取每一維數據
???????? {
???????????? ifs>>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<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核心對象標志位設為true
???????? return;??????????????? //返回
???? }
???? dp.SetKey(false);??? //若非核心對象,則將dp核心對象標志位設為false
?}

?
?/*
?函數:執行聚類操作
?說明:執行聚類操作
?參數:
?返回值: true;??? */
?bool ClusterAnalysis::DoDBSCANRecursive()
?{
???? unsigned long clusterId=0;??????????????????????? //聚類id計數,初始化為0
???? for(unsigned long i=0; i<dataNum;i++)??????????? //對每一個數據點執行
???? {
???????? DataPoint& dp=dadaSets[i];??????????????????? //取到第i個數據點對象
???????? if(!dp.isVisited() && dp.IsKey())??????????? //若對象沒被訪問過,并且是核心對象執行
???????? {
???????????? dp.SetClusterId(clusterId);??????????????? //設置該對象所屬簇ID為clusterId
???????????? dp.SetVisited(true);??????????????????? //設置該對象已被訪問過
???????????? KeyPointCluster(i,clusterId);??????????? //對該對象領域內點進行聚類
???????????? clusterId++;??????????????????????????? //clusterId自增1
???????? }
???????? //cout << "孤立點/T" << i << endl;
???? }

???? cout <<"共聚類" <<clusterId<<"個"<< endl;??????? //算法完成后,輸出聚類個數
???? return true;??? //返回
?}

?/*
?函數:對數據點領域內的點執行聚類操作
?說明:采用遞歸的方法,深度優先聚類數據
?參數:
?unsigned long dpID;??????????? //數據點id
?unsigned 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;??????? //數據點1
?DataPoint& dp2;??????? //數據點2
?返回值: double;??? //兩點之間的距離??????? */
?double ClusterAnalysis::GetDistance(DataPoint& dp1, DataPoint& dp2)
?{
???? double distance =0;??????? //初始化距離為0
???? for(int i=0; i<DIME_NUM;i++)??? //對數據每一維數據執行
???? {
???????? distance += pow(dp1.GetDimension()[i] - dp2.GetDimension()[i],2);??? //距離+每一維差的平方
???? }
???? return pow(distance,0.5);??????? //開方并返回距離
?}


算法調用就簡單了:

?

?

?


#include "ClusterAnalysis.h"
?#include <cstdio>

?using namespace std;

?int main()
?{
???? ClusterAnalysis myClusterAnalysis;??????????????????????? //聚類算法對象聲明
???? myClusterAnalysis.Init("D://1108//XY.txt",500,9);??????? //算法初始化操作,指定半徑為15,領域內最小數據點個數為3,(在程序中已指定數據維度為2)
???? myClusterAnalysis.DoDBSCANRecursive();??????????????????? //執行聚類算法
???? myClusterAnalysis.WriteToFile("D://1108//XYResult.txt");//寫執行后的結果寫入文件

???? system("pause");??? //顯示結果
???? return 0;??????????? //返回
?}

上文就是關于C++實現DBSCAN聚類的算法介紹,相信認真看完的朋友都已經清楚了,當你遇到關于程序方面的問題時就登陸武林技術頻道吧!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美在线视频免费观看| 日本欧美一二三区| 视频在线观看一区二区| 亚洲精品wwww| 亚洲黄页网在线观看| 亚洲精品aⅴ中文字幕乱码| 91视频国产一区| 国产精品1区2区在线观看| 免费99精品国产自在在线| 1769国内精品视频在线播放| 少妇高潮久久久久久潘金莲| 国产精品美女视频网站| 国产精品视频成人| 狠狠躁夜夜躁久久躁别揉| 亚洲成av人片在线观看香蕉| 国模精品视频一区二区三区| 中文字幕在线日韩| 日韩亚洲第一页| 8090成年在线看片午夜| 欧美寡妇偷汉性猛交| 国产在线观看不卡| 精品久久久一区| 亚洲在线免费视频| 精品久久香蕉国产线看观看亚洲| 91精品国产自产在线观看永久| 日韩av影视在线| 日韩av色综合| 欧美日产国产成人免费图片| 国产精品老女人精品视频| 国语自产精品视频在免费| 亚洲综合中文字幕68页| 日韩av在线资源| 少妇久久久久久| 精品中文字幕久久久久久| 久久精品这里热有精品| 欧美精品免费看| 91精品国产综合久久香蕉| 日韩电影在线观看免费| 国产美女精彩久久| 亚洲视频在线免费观看| 欧美成人精品xxx| 国产精品久久久久免费a∨大胸| 性亚洲最疯狂xxxx高清| 欧美一级电影在线| 亚洲精品一区二区网址| 日韩精品极品视频| 国产精品九九久久久久久久| 精品国产拍在线观看| 国产在线日韩在线| 欧美性猛交xxxx黑人| 国产香蕉精品视频一区二区三区| 欧美日韩亚洲精品一区二区三区| 欧美国产日产韩国视频| 日韩最新中文字幕电影免费看| 丝袜亚洲另类欧美重口| 国产a级全部精品| 国产成人啪精品视频免费网| www.欧美视频| 欧美亚洲国产精品| 欧美日韩激情美女| 国内久久久精品| 亚洲欧洲偷拍精品| 欧美日韩国产成人| 欧美日韩国产中字| 国产一区二区三区视频| 欧美成人性色生活仑片| 成人免费视频xnxx.com| 欧美肥婆姓交大片| 日韩在线免费视频观看| 91中文字幕在线观看| 高清日韩电视剧大全免费播放在线观看| 欧美精品福利在线| 国产丝袜视频一区| 欧美高清在线视频观看不卡| 第一福利永久视频精品| 国产精品白嫩初高中害羞小美女| 国产精品黄色影片导航在线观看| 国产一区二区黄| 成人中文字幕在线观看| 91福利视频在线观看| 日韩高清av一区二区三区| 亚洲第一av网| 自拍偷拍免费精品| 4438全国成人免费| 日韩在线观看网址| 色伦专区97中文字幕| 日韩在线欧美在线| 久久久久久国产精品三级玉女聊斋| 国产精品久久激情| 日韩电影中文字幕在线观看| 精品久久久久久| 欧美影院在线播放| 成人在线视频福利| 一区二区三区天堂av| 国产99久久久欧美黑人| 亚洲国产成人久久综合一区| 在线视频亚洲欧美| 精品久久久久久中文字幕一区奶水| 久久伊人色综合| 久久99热精品这里久久精品| 国产日韩换脸av一区在线观看| 九九热这里只有精品6| 欧美精品久久一区二区| 亚洲片在线资源| 美女999久久久精品视频| 中文字幕欧美日韩在线| 成人黄色短视频在线观看| 欧美精品久久久久久久久久| 91综合免费在线| 国产精品久久中文| 久久99热精品这里久久精品| 日本久久亚洲电影| 日韩成人在线网站| 国产精品日韩在线观看| 国产精品高潮呻吟久久av无限| 亚洲人精品午夜在线观看| 成人国产在线激情| 91精品视频免费看| 日韩久久免费视频| 搡老女人一区二区三区视频tv| 亚洲精品国产欧美| 懂色av中文一区二区三区天美| 欧美疯狂做受xxxx高潮| 欧美理论片在线观看| 亚洲欧美一区二区激情| 亚洲成人精品久久| 欧美极品少妇xxxxⅹ裸体艺术| 亚洲精品午夜精品| 日韩欧美国产高清91| 欧美视频免费在线| 亚洲精品xxxx| 亚洲电影在线观看| 欧美三级xxx| 亚洲自拍偷拍福利| 亚洲一区二区三区xxx视频| 国产成人精品a视频一区www| 亚洲社区在线观看| 精品二区三区线观看| www.国产一区| 91影视免费在线观看| 欧美亚洲视频在线看网址| 国产午夜精品免费一区二区三区| 国产视频久久久久久久| 91精品久久久久久久久久久| 综合欧美国产视频二区| 国产噜噜噜噜久久久久久久久| 中文字幕亚洲二区| 久久躁狠狠躁夜夜爽| 久久精品国产电影| 亚洲大胆人体在线| 国产精品三级久久久久久电影| 97国产suv精品一区二区62| 亚洲成人a**站| 亚洲欧美日韩中文视频| 欧美精品一区三区| 久久久精品2019中文字幕神马| 国产精品91一区| 亚洲午夜未满十八勿入免费观看全集| 国产va免费精品高清在线观看| 亚洲人成在线一二| 日韩高清不卡av| 中文字幕成人在线| 欧美国产亚洲精品久久久8v| 久久视频在线观看免费|