dbscan算法c語言實現,用C++實現DBSCAN聚類算法

這幾天由于工作需要,對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; i

{

this->dimension[i]=dimension[i];

}

}

//設置維度數據

void DataPoint::SetDimension(double* dimension)

{

for(int i=0; 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& 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 << "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

{

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

{

SetArrivalPoints(dadaSets[i]);??????????? //計算數據點領域內對象

}

return true;??? //返回

}

/*

函數:將已經過聚類算法處理的數據集合寫回文件

說明:將已經過聚類結果寫回文件

參數:

char* fileName;??? //要寫入的文件名

返回值: true??? */

bool ClusterAnalysis::WriteToFile(char* fileName )

{

ofstream of1(fileName);??????????????????????????????? //初始化文件輸出流

for(unsigned long i=0; i

{

for(int d=0; d

of1<

of1 << dadaSets[i].GetClusterId() <

}

of1.close();??? //關閉輸出文件流

return true;??? //返回

}

/*

函數:設置數據點的領域點列表

說明:設置數據點的領域點列表

參數:

返回值: true;??? */

void ClusterAnalysis::SetArrivalPoints(DataPoint& dp)

{

for(unsigned long i=0; 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

{

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 <

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& arrvalPoints = srcDp.GetArrivalPoints();??????? //獲取對象領域內點ID列表

for(unsigned long i=0; i

{

DataPoint& desDp = dadaSets[arrvalPoints[i]];??? //獲取領域內點數據點

if(!desDp.isVisited())??????????????????????????? //若該對象沒有被訪問過執行

{

//cout << "數據點\t"<< desDp.GetDpId()<

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

{

distance += pow(dp1.GetDimension()[i] - dp2.GetDimension()[i],2);??? //距離+每一維差的平方

}

return pow(distance,0.5);??????? //開方并返回距離

}

算法調用就簡單了:

復制代碼 代碼如下:

#include "ClusterAnalysis.h"

#include

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;??????????? //返回

}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/529636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/529636.shtml
英文地址,請注明出處:http://en.pswp.cn/news/529636.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

小世界網絡模型代碼 c 語言,新的小世界網絡模型實現文本特征的提取方法與流程...

本發明涉及語義網絡技術領域&#xff0c;具體涉及新的小世界網絡模型實現文本特征的提取方法。背景技術&#xff1a;目前常用的文本特征提取方法&#xff0c;包括詞頻-反文檔頻率方法—TF-IDF、信息增益方法、互信息等方法&#xff1b;TF-IDF的簡單結構并不能有效地反映詞匯或短…

米4用linux刷機救轉,小米4變磚之后如何刷機自救?大神教你小米4線刷救磚方法...

三&#xff1a;使用miflash工具刷機的步驟本工具適用于小米&#xff0c;華為&#xff0c;聯想等手機品牌高通版本&#xff0c;不只是小米專用&#xff0c;教程僅供參考&#xff0c;看完一遍后再刷機。第一步&#xff1a;刷機工具安裝1.下載小米手機刷機工具MiPhone2015731&…

android動態更新配置文件,Android如何動態修改Manifest文件

修改manifest文件Android Manifest.xml&#xff0c;添加相應的聲明。在這里&#xff0c;我們需要將新定義的活動PrefsActivity注冊到manifest文件。同前面一樣&#xff0c;在Eclipse中打開AndroidManifest.xml文件會默認進入Eclipse提供的圖形化編輯界面。單擊Application選項卡…

com.android.phone已停止運行怎么解決方法,com.android.phone已停止運行怎么解決

在安卓手機上&#xff0c;不少用戶都會遇過com.android.phone已停止的彈窗&#xff0c;尤其經常刷機的最明顯。導致的原因實在太多&#xff0c;有刷機步驟不對的&#xff0c;亂改系統文件的&#xff0c;這里小編綜合網上的情況以及自身經歷&#xff0c;給廣大安卓用戶一個com.a…

android動畫放大后縮小,Android 補間動畫 scale(縮放)

今天又遇到了關于Android 動畫方面的問題&#xff0c;免不了一番瘋狂找資料&#xff0c;所幸解決了自己的問題&#xff0c;為了避免以后遇到同樣的問題&#xff0c;再次到處找資料&#xff0c;于是決定寫篇隨筆記錄下來&#xff0c;方便自己方便大家^_^&#xff1b;廢話就不說了…

android 生成泛型對象,java android解析多層含有泛型對象的json數據獲取不到泛型類型解析失敗解決辦法...

####問題描述* java 解析多層含有泛型對象的json數據獲取不到泛型類型* 如果將泛型改成實際的類型就能正常解析* 如果不改成實際的類型泛型數據被解析成com.google.gson.internal.LinkedTreeMap* 如果強制轉換報錯:java.lang.ClassCastException: com.google.gson.internal.Lin…

android 機器人動畫,Android 5.X與Android4.X版本機器人動畫的區別以及制作動畫的方法...

今天翻了下墻&#xff0c;解決了一直以來的疑惑問題&#xff1a;為什么Android5.0以及6.0的recovery版本&#xff0c;機器人動畫怎么就只有一張圖片&#xff1f;這個問題&#xff0c;我百思不得其解&#xff0c;看了很多網文&#xff0c;也只是有了個概念。請參考以下文檔&…

android盒子smb,普通安卓盒子smb方法 - 懷舊游戲長廊 - A9VG電玩部落論壇 - Powered by Discuz!...

本帖最后由 slime525 于 2018-10-20 21:00 編輯1安卓下安裝盒子伴侶一鍵自動安裝Optware2win下安裝Putty&#xff0c;記下盒子ip端口&#xff0c;賬戶密碼分別是&#xff1a;root&#xff0c;toor。小寫&#xff01;3然后直接輸入&#xff1a;ipkg-opt install samba就會自動下…

android .9編譯,在Ubuntu 9.04下編譯Android源碼

一直都是刷官方的版本&#xff0c;準備自己編譯一下刷機。首先是下載&#xff0c;Android的源碼是托管在Linux Kernel的源碼站點&#xff0c;所以版本工具是git。關于git的使用和安裝請見我的另一篇文章《在Ubuntu Server上安裝Git》。創建一個存放Andorid的目錄&#xff0c;然…

android reshare.c病毒,惡意軟件分析 URL鏈接掃描 免費在線病毒分析平臺 | 魔盾安全分析...

META-INF/MANIFEST.MFtNDfEFTy~s{Cg\V/OxIl[Mf"JC E_UcB1$^x6"i]6U#3D5Tmw>20#&hG;bVl*XK]xJU"#k})ek?w&);ViFd0iCFvye{(jB9w%^!yEj2,DGAW|^8ws%bD*eQ6n]fI_w3_nP_gxWll)zf[}l[[Rpn7x7?vbxfuVzgOj^x^lZ,b;%TK7k^mro)AYQJ2o^sL/EDh"^qND9V|Gn(…

imeoptions android,軟鍵盤小記Android:imeOptions

1.actionUnspecified 未指定,對應常量EditorInfo.IME_ACTION_UNSPECIFIED.2.actionNone 沒有動作,對應常量EditorInfo.IME_ACTION_NONE3.actionGo 去往,對應常量EditorInfo.IME_ACTION_GO4.actionSearch 搜索,對應常量EditorInfo.IME_ACTION_SEARCH5.actionSend 發送,對應常量E…

android rn框架開發的例子,RN與安卓通信架構篇

本篇文章介紹的搭建Android與Rn之間的簡易通信架構&#xff0c;需要了解通信的基本使用的同學可以參考下面的鏈接開篇先上圖 - “簡易版的通信架構圖”RN與Android之間通信的架構圖本架構實現的功能有&#xff1a;自定義通信規則&#xff0c;并以Json作為數據傳輸格式進行傳輸實…

android 查詢所有圖片和視頻,Android系統詳解之獲取圖片和視頻的縮略圖

從Android 2.2開始系統新增了一個縮略圖ThumbnailUtils類&#xff0c;位于framework的android.media.ThumbnailUtils位置&#xff0c;可以幫助我們從mediaprovider中獲取系統中的視頻或圖片文件的縮略圖&#xff0c;該類提供了三種靜態方法可以直接調用獲取。1.static Bitmap c…

node將圖片轉換成html文件,node+puppeteer將整個網頁html轉換為圖片并保存【滾動截屏】...

Puppeteer 是 Chrome 開發團隊在 2017 年發布的一個 Node.js 包&#xff0c;用來模擬 Chrome 瀏覽器的運行。demo只支持將簡單不需要翻頁&#xff0c;不需要登陸的頁面轉換為圖片需要node環境&#xff0c;以及npm或cnpm包管理工具(自行百度)開始進入一個新的項目目錄&#xff0…

html hover效果下拉個框,關于下拉菜單(CSS)中,“:hover”樣式的設置問題?

各位大大&#xff0c;請幫忙解決一下這個問題&#xff0c;先謝謝&#xff01;由于之前的代碼不是全部帖出&#xff0c;可能造成一點信息誤解。以下是針對這個問題另外寫的代碼&#xff1a;.nav {width: 50px;height: 50px;overflow:hidden;background-color: #09F;transition: …

計算機基礎知識離線作業答案,浙大遠程教育計算機離線作業1.計算機基礎知識題...

浙大遠程教育計算機離線作業1.計算機基礎知識題第1章 計算機基礎知識(單選題)這些題目必須做一遍&#xff0c;來自統考題庫(期末考試題也多半出在這里)&#xff0c;參考答案在另一個Word文檔中(上傳自己做的答案后才可以下載…)。據說&#xff0c;統考題庫中大約有10,000測試題…

go 生成hash_go基礎之map-寫在前面(一)

為什么分析map在計算機編程語言當中&#xff0c;用的最多的數據結構估計就是map。map以他近乎o(1)的查找效率和修改效率讓他在大多數場景下都比較受青睞。map的常規的實現方式都是hash其他數據結構&#xff0c;如java是hash紅黑樹&#xff0c;而我現在即將要分析的go的實現方式…

大學數學建模大賽是用計算機,北京大學第十屆“江澤涵杯”數學建模與計算機應用競賽試題...

消息來源&#xff1a;http://www.math.pku.edu.cn:8000/news/read.php?newsid8014A題&#xff1a;投籃問題投籃是籃球運動中一項關鍵性技術&#xff0c;是一項重要的得分手段。在籃球賽中有三種特殊的投籃方式&#xff0c;“三分球”、“兩分球”和“一分球(罰籃)”。其中&…

dynamo方程怎么寫_【簡明自控】為什么特征方程如此重要

簡明自動控制——為什么特征方程如此重要。熱場視頻&#xff1a;自平衡桿-雙軸反作用輪倒立擺_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com頂個棍子&#xff01;具有主動腳輪的全向移動機器人_嗶哩嗶哩 (゜-゜)つロ 干杯~-bilibili?www.bilibili.com我自行車怎么少…

用戶計算機可以通過電話撥號,用戶計算機可以通過大型局域網、小型局域網、無線連接、電話撥號和()等方式接入Internet。...

_在保險合同中&#xff0c;用于體現保險利益載體的保險對象條款&#xff0c;被稱為()條款。何為C/H比&#xff1f;原料中的C/H比與原性能的關系是什么&#xff1f;選址意見書、規劃條件、建設用地規劃許可證、建設工程規劃許可證的有效期為()福建木偶戲頗負盛名&#xff0c;以(…