计量地理-聚类

el/2024/3/2 12:39:48

按照计量地理思想,对距离矩阵进行聚类,数据如

6
0.0 0.375 0.483 1.749 1.516 1.972
0.375 0.0 0.776 1.596 1.336 1.743
0.483 0.776 0.0 1.926 1.662 2.154
1.749 1.596 1.926 0.0 0.501 0.693
1.516 1.336 1.662 0.501 0.0 0.589

1.972 1.743 2.154 0.693 0.589 0.0

第一行为数据个数,下面为距离矩阵,可以下三角(上三角)全为0。

// ClusterAnalysis.cpp : Defines the entry point for the console application.//#include "stdafx.h"
#include "iostream"
using namespace std;
#include "iomanip"#include "vector"
#include "string"typedef struct {int iClaNO1;int iClaNO2;int iNO;			// 标记聚类的次序
}NEW_NODE;typedef struct {int iSample1;int iSample2;float fDist;
}DIST_NODE;void Bubble(int *sort,int iCount)
{for(int i = 0;i < iCount - 1;i++){for(int j = 0;j < iCount - i - 1;j++){float temp;if(sort[j + 1] < sort[j]){temp = sort[j];sort[j] = sort[j + 1];sort[j + 1] = temp;}}}
}int _tmain(int argc, _TCHAR* argv[])
{int iSampleCount;					// 要分类的样本数float **m_data;						// 存储距离矩阵	string strFile = "COST_MATRIX.txt";FILE *fp;if((fp=fopen(strFile.c_str(),"r"))==NULL){printf("Cannot open this file\n");exit(0);}fscanf(fp,"%d",&iSampleCount);m_data = new float *[iSampleCount];for(int i = 0;i < iSampleCount;i++)m_data[i] = new float[iSampleCount];for(int i = 0;i < iSampleCount;i++)for(int j = 0;j < iSampleCount;j++)fscanf(fp,"%f",&m_data[i][j]);// 原始数据输出到屏幕/*for(int i = 0;i < iSampleCount;i++){for(int j = 0;j < iSampleCount;j++)cout << setw(5) << m_data[i][j] << "   ";cout << endl;}*/// 存储初始距离矩阵中的元素vector<DIST_NODE> vecDist;for(int i = 0;i < iSampleCount;i++){for(int j = i + 1;j < iSampleCount;j++){DIST_NODE temp;temp.fDist = m_data[i][j];temp.iSample1 = i + 1;temp.iSample2 = j + 1;vecDist.push_back(temp);}}int iVecSize = vecDist.size();	// 获取距离中的最大值float flMax = vecDist.at(0).fDist;for(int i = 0;i < iSampleCount;i++)if(flMax < vecDist.at(i).fDist)flMax = vecDist.at(i).fDist;cout << "开始聚类过程" << endl;vector<NEW_NODE> vecResult;vector<int> vecNO;int iNO = 0;while(true){vector<NEW_NODE> vecNew;float flMin = flMax;iVecSize = vecDist.size();if(vecDist.size() == 0)break;		if(vecDist.size() == 1){NEW_NODE temp;temp.iClaNO1 = vecDist.at(0).iSample1;temp.iClaNO2 = vecDist.at(0).iSample2;temp.iNO     = iNO +1;vecResult.push_back(temp);vecNO.push_back(iNO + 1);vecDist.clear();continue;}// 确定最小值		for(int i = 0;i < iVecSize;i++){if(flMin >= vecDist.at(i).fDist &&  vecDist.at(i).fDist!=-1)flMin = vecDist.at(i).fDist;					}// 根据最小值确定相应的聚类单元// 存储聚类单元的编号,有可能重复for(int i = 0;i < iVecSize;i++){			if(flMin == vecDist.at(i).fDist){					NEW_NODE temp;temp.iClaNO1 = vecDist.at(i).iSample1;temp.iClaNO2 = vecDist.at(i).iSample2;temp.iNO = iNO + 1;vecNew.push_back(temp);				}			}iNO++;	// 为下次聚类准备vecNO.push_back(iNO);// 剔除vecNew中重复的类别号码int iNewCount = vecNew.size();int *iNewData = new int[2 * iNewCount];		vector<int> vecNewDel;		// 剔除重复的点之后结果if(iNewCount > 1){int iNewCount = vecNew.size();for(int i = 0;i < iNewCount;i++){iNewData[i * 2] = vecNew.at(i).iClaNO1;iNewData[i * 2 + 1] = vecNew.at(i).iClaNO2;}// 对iNewData进行冒泡排序Bubble(iNewData,iNewCount * 2);for(int i = 0;i < iNewCount * 2;i++){for(int j = i + 1;j < iNewCount * 2;j++)if(iNewData[i] != iNewData[j]){vecNewDel.push_back(iNewData[i]);if(j == iNewCount * 2 - 1)vecNewDel.push_back(iNewData[i + 1]);break;}else{if(i == iNewCount * 2 - 2)vecNewDel.push_back(iNewData[i]);break;}}}		else{vecNewDel.push_back(vecNew.at(0).iClaNO1);vecNewDel.push_back(vecNew.at(0).iClaNO2);}// 确定要合并的类之后,更新vecDist栈中的内容// 首先将未参与聚类的样本取出,然后再计算新类到其余样本之间的距离vector<DIST_NODE> vecTemp;		for(int i = 0;i < vecDist.size();i++){int iSampleNo1 = vecDist.at(i).iSample1;int iSampleNo2 = vecDist.at(i).iSample2;bool blCluster = false;for(int j = 0;j < vecNewDel.size();j++){if(iSampleNo1 == vecNewDel.at(j) || iSampleNo2 == vecNewDel.at(j)){blCluster = true;break;}}if(!blCluster){DIST_NODE temp = vecDist.at(i);vecTemp.push_back(temp);}}int iUnSize = vecTemp.size();int *iUnCluster;		vector<int>vecUnCluster;if(!vecTemp.empty()){iUnCluster = new int[2 * iUnSize];	for(int i = 0;i < iUnSize;i++){iUnCluster[i * 2] = vecTemp.at(i).iSample1;iUnCluster[i * 2 + 1] = vecTemp.at(i).iSample2;}Bubble(iUnCluster,iUnSize * 2);for(int i = 0;i < iUnSize * 2;i++){for(int j = i + 1;j < iUnSize * 2;j++)if(iUnCluster[i] != iUnCluster[j]){vecUnCluster.push_back(iUnCluster[i]);if(j == iUnSize * 2 - 1)vecUnCluster.push_back(iUnCluster[i + 1]);break;}else{if(i == iUnSize * 2 - 2)vecUnCluster.push_back(iUnCluster[i]);break;}}}	else{		// if(!vecTemp.empty())for(int i = 0;i < vecDist.size();i++){bool blCluster = false;int iSampleNo1 = vecDist.at(i).iSample1;int iSampleNo2 = vecDist.at(i).iSample2;for(int j = 0;j < vecNewDel.size();j++){if(iSampleNo1 == vecNewDel.at(j)){blCluster = true;break;}}if(!blCluster){if(vecUnCluster.empty())vecUnCluster.push_back(iSampleNo1);else{bool blAdd = true;for(int k = 0;k < vecUnCluster.size();k++){if(iSampleNo1 == vecUnCluster.at(k)){blAdd = false;break;}}if(blAdd)vecUnCluster.push_back(iSampleNo1);}}blCluster = false;for(int j = 0;j < vecNewDel.size();j++){if(iSampleNo2 == vecNewDel.at(j)){blCluster = true;break;}}if(!blCluster){if(vecUnCluster.empty())vecUnCluster.push_back(iSampleNo2);else{bool blAdd = true;for(int k = 0;k < vecUnCluster.size();k++){if(iSampleNo2 == vecUnCluster.at(k)){blAdd = false;break;}}if(blAdd)vecUnCluster.push_back(iSampleNo2);}}// if(!blCluster)}}// 计算新类到未参与聚类样本点之间的距离iSampleCount++;		// 标记新的样本点号for(int i = 0;i < vecUnCluster.size();i++){DIST_NODE temp;temp.iSample1 = vecUnCluster.at(i);temp.iSample2 = iSampleCount;float fTemp = flMax;// 本次聚类过程的新类由哪几个样本构成,即iSampleCount由谁构成for(int j = 0;j < vecNewDel.size();j++){int iClass = vecNewDel.at(j);// 在vecDist中遍历,寻找与temp.iSample1、iClass所对应的节点for(int k = 0;k < vecDist.size();k++){if((temp.iSample1 == vecDist.at(k).iSample1 && iClass == vecDist.at(k).iSample2) ||(temp.iSample1 == vecDist.at(k).iSample2 &&iClass == vecDist.at(k).iSample1)){if(fTemp > vecDist.at(k).fDist)fTemp = vecDist.at(k).fDist;break;}}}temp.fDist = fTemp;vecTemp.push_back(temp);}// 清空vecDist,用vecTemp中的内容进行替换vecDist.clear();for(int i = 0;i < vecTemp.size();i++)vecDist.push_back(vecTemp.at(i));		//  将每次聚类的结果保存for(int i = 0;i < vecNew.size();i++)vecResult.push_back(vecNew.at(i));}//  输出每次的聚类结果	for(int i = 0;i < vecNO.size();i++){		int iNO = vecNO.at(i);cout << "第" << iNO << "次聚类对象是:  ";for(int j = 0;j < vecResult.size();j++)if(iNO == vecResult.at(j).iNO)cout << vecResult.at(j).iClaNO2 << "和" << vecResult.at(j).iClaNO1 << "; ";cout<< endl;}cout << "结束聚类过程" << endl;system("pause");return 0;
}


http://www.ngui.cc/el/4465891.html

相关文章

C++二维数组动态分配内存

演示了结构体与普通二维指针的动态分配 #include "stdafx.h"struct POINT{double x,y; };int _tmain(int argc, _TCHAR* argv[]) {int **pData;POINT ** pPoint;int iCol 5;//列数int iRow 5;//行数pData new int*[iRow];pPoint new POINT*[iRow];for(int i 0;…

计量地理-最短路径

求解最短路径&#xff0c;输入如下 7 70 9 7 2 -1 -1 -1-1 0 -1 -1 5 -1 -1-1 5 0 2 -1 -1 -1-1 -1 4 0 -1 3 -1-1 -1 -1 -1 0 -1 6-1 3 -1 -1 11 0 9 -1 -1 -1 -1 -1 -1 0 第一行存储行列数 // ShortestRoute.cpp : Defines the entry point for the con…

计量地理-PrincipalCA主成分析

输入如下&#xff1a; 9 1 -0.8140 -0.2168 0.3355 -0.186 0.5417 0.4237 0.0378 -0.6547-0.8140 1 0.4602 -0.6613 -0.0874 -0.7306 -0.3136 -0.0634 0.8749-0.2168 0.4602 1 0.6603 -0.2394 -0.5314 -0.2072 0.0269 0.68530.3355 -0.6613 -0.6603 1 0.3829 0.6197 0.188…

计量地理-最优点的位置

输入如下&#xff1a;每一行是居民点位置和人口数 5 5 2 10 10 2.5 5 35 2 10 27.5 2.5 15 5 2 15 15 3 15 40 2 17.5 25 3.5 20 15 4 25 30 4 25 45 2 30 10 4 35 20 5 40 5 3 42.5 25 6 45 35 5 52.5 42.5 5.5 55 35 4.5 55 5 4 57.5 10…

C#-交互式绘图

结果如图所示&#xff1a; using System;using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Windows.Forms;namespace 交互式绘…

测绘-编写数字高程模型(DEM)内插程序

一、 实习目的 掌握移动曲面法数字高程模型内插原理及其内插子程序的设计方法&#xff0c;了解其它逐点高程内插方法的基本原理。 二、 实习内容 根据提供的10个数据点的坐标&#xff08;Xn,Yn,Zn&#xff09;和待求点的平面坐标&#xff08;Xp,Yp&#xff09;&#xff0…

C-链表

上图为效果图 #include <stdio.h>#include <stdlib.h> #include <malloc.h> typedef struct Node{ int data;struct Node *next;} SLIST;void inlist(SLIST *l,int a){SLIST *p,*q;int i;p(SLIST *)malloc(sizeof(SLIST));l->nextp;for(ia;i&…

获取MFC主框架

在MainFrm里面定义的是主框架的东西&#xff0c;也就是一启动就会运行的&#xff0c;所以在后面要加东西的话得获得一开始定义的框架 CMainFrame* pFrame (CMainFrame*)AfxGetApp()->m_pMainWnd; pFrame->m_wndFileView.FillFileView(); MFC一个程序只会有一个从头到尾的…

C++ listCtrl点击列头自动排序

一个函数; void CDialogTableSum::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) {NM_LISTVIEW* pNMListView (NM_LISTVIEW*)pNMHDR;int selectcol pNMListView->iSubItem;//获得当前所选列int listcount;//总行数listcount m_listCtrl->GetItemCount();CString t…

C++-MFC Office风格的界面,ListCtrl点击选中后高亮

一个函数就可以搞定&#xff1a; void CListCtrlView::OnCustomdrawList( NMHDR *pNMHDR, LRESULT *pResult ) {NMLVCUSTOMDRAW* pLVCD reinterpret_cast<NMLVCUSTOMDRAW*>( pNMHDR );*pResult CDRF_DODEFAULT;if ( CDDS_PREPAINT pLVCD->nmcd.dwDrawStage ){*pRes…