博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
K均值算法实现
阅读量:5114 次
发布时间:2019-06-13

本文共 3978 字,大约阅读时间需要 13 分钟。

运行环境:Ubuntu+Code::Blocks(G++)

K-均值:在D(数据集)中随机地选择k个对象,每个对象代表一个簇的初始均值或中心。对剩下的每个对象,根据其与各个簇中心的欧式距离,将它分配到最相似的簇中。(不能保证k-均值方法收敛于全局最优解,并且它常常终止于一个局部最优解。可以不同的初始簇中心,多次运行k-均值算法。)

代码为3个簇,初始的簇中心为输入的前三个点。(代码是六七月份写的,直接放上来。)

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #define OP ',' 7 #define SET_SIZE 3 //簇的个数 8 9 using namespace std; 10 const double EXP = 1e-6;//用于判断新的中心点与原中心点的距离,如果比exp要小则说明聚类结束 11 12 //定义的点的坐标 13 typedef struct point 14 { 15 double xAxle; 16 double yAxle; 17 point() 18 { 19 xAxle = 0; 20 yAxle = 0; 21 } 22 point(double _x,double _y) 23 { 24 xAxle = _x; 25 yAxle = _y; 26 } 27 }Point; 28 29 //读取文件里面的内容,到numSave数组里面去 30 void readFile(ifstream &inFile,const string &fileName,vector
&numSave) 31 { 32 inFile.clear(); 33 34 inFile.open(fileName.c_str()); 35 if(!inFile) 36 { 37 cout << "无法打开输入文件!" << endl; 38 } 39 40 //一行一行的读取 41 string temp; 42 while(getline(inFile,temp)) 43 { 44 //文件里面一行是一个坐标点 45 double x = atof(temp.substr(0,temp.find(OP)).c_str()); 46 double y = atof(temp.substr(temp.find(OP) + 1,temp.size()-1).c_str()); 47 48 numSave.push_back(Point(x,y)); 49 } 50 51 inFile.close(); 52 } 53 54 //计算距离值 55 double calDistance(Point &a,Point &b) 56 { 57 return sqrt((a.xAxle - b.xAxle) * (a.xAxle - b.xAxle) + (a.yAxle - b.yAxle)*(a.yAxle - b.yAxle)); 58 } 59 60 //计算一个簇里面的均值以获得中心点 61 void calAverage(vector
num,double &xValueAver,double &yValueAver) 62 { 63 int xValue = 0,yValue = 0; 64 for(unsigned int i = 0;i < num.size();i ++) 65 { 66 xValue += num[i].xAxle; 67 yValue += num[i].yAxle; 68 } 69 70 //获得平均值 71 xValueAver = (double)xValue/num.size(); 72 yValueAver = (double)yValue/num.size(); 73 74 } 75 76 //根据簇中心得到集合,getSetValue存储每一个簇里面的元素 77 void getSet(vector
&numSave,vector
&setCentre,vector
(&getSetValue)[SET_SIZE]) 78 { 79 80 for(unsigned int i = 0;i < numSave.size();i ++) 81 { 82 //设置一个最大值,为了找到最小值 83 double temp = 100000000.0; 84 //记录最小的距离numSave[i]的值 85 unsigned int k = 0; 86 for(unsigned int j = 0;j < SET_SIZE;j ++) 87 { 88 //计算距离 89 double dis = calDistance(numSave[i],setCentre[j]); 90 if(temp > dis) 91 { 92 temp = dis; 93 k = j;//保留最小距离的那个编号 94 } 95 } 96 //将最小值放在相应编号的簇里面 97 getSetValue[k].push_back(numSave[i]); 98 } 99 }100 101 void k_average(vector
&numSave,ofstream &os)102 {103 vector
setCentre;104 vector
getSetValue[SET_SIZE];105 vector
tempCentre;//用来保存之前的数据,方便对比106 107 //初始时将数据的前几个(定义的簇中心个数)作为中心点108 for(unsigned int i = 0;i < SET_SIZE && i < numSave.size();i ++)109 {110 setCentre.push_back(numSave[i]);111 }112 113 while(true)114 {115 for(unsigned int i = 0;i < SET_SIZE;i ++)116 {117 getSetValue[i].clear();118 }119 //根据簇中心找到与簇中心相关的点(距离近的点)120 getSet(numSave,setCentre,getSetValue);121 122 tempCentre = setCentre;123 bool flag = true;124 for(unsigned int i = 0;i < SET_SIZE;i ++)125 {126 //输出簇中心点127 os << setCentre[i].xAxle << " and " << setCentre[i].yAxle << endl;128 /*129 for(unsigned int j = 0;j < getSetValue[i].size();j ++)130 {131 os << getSetValue[i][j].xAxle << " " << getSetValue[i][j].yAxle << "----";132 }133 os << endl;134 */135 //根据新的集合获得新的簇中心136 calAverage(getSetValue[i],setCentre[i].xAxle,setCentre[i].yAxle);137 }138 139 //当其中有一项当前的簇中心相对于之前的移动了较大距离就继续寻找140 for(unsigned int i = 0;i < SET_SIZE;i ++)141 {142 if(fabs(setCentre[i].xAxle - tempCentre[i].xAxle) > EXP || fabs(setCentre[i].yAxle - tempCentre[i].yAxle) > EXP )143 {144 flag = false;145 break;146 }147 }148 149 os << endl;150 //当每个簇中心不再变化时就不用找了151 if(flag)152 {153 break;154 }155 156 }157 158 }159 160 int main()161 {162 ifstream inFile;163 vector
numSave;164 readFile(inFile,"input.txt",numSave);165 166 ofstream outFile;167 outFile.open("output.txt");168 if(!outFile)169 {170 cout << "不能打开文件。请检查文件!" << endl;171 }172 k_average(numSave,outFile);173 return 0;174 }
代码如下:

 

转载于:https://www.cnblogs.com/Shirlies/p/3277100.html

你可能感兴趣的文章
(安卓)一般安卓开始界面 Loding 跳转 实例 ---亲测!
查看>>
Mysql 索引优化 - 1
查看>>
LeetCode(3) || Median of Two Sorted Arrays
查看>>
大话文本检测经典模型:EAST
查看>>
待整理
查看>>
一次动态sql查询订单数据的设计
查看>>
C# 类(10) 抽象类.
查看>>
Vue_(组件通讯)子组件向父组件传值
查看>>
jvm参数
查看>>
我对前端MVC的理解
查看>>
Silverlight实用窍门系列:19.Silverlight调用webservice上传多个文件【附带源码实例】...
查看>>
2016.3.31考试心得
查看>>
mmap和MappedByteBuffer
查看>>
Linux的基本操作
查看>>
转-求解最大连续子数组的算法
查看>>
对数器的使用
查看>>
【ASP.NET】演绎GridView基本操作事件
查看>>
ubuntu无法解析主机错误与解决的方法
查看>>
尚学堂Java面试题整理
查看>>
MySQL表的四种分区类型
查看>>