一,k-means算法介绍:
k-means算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。
k-means算法的工作过程说明如下:首先从n个数据对象任意选择 k 个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数。k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。
二,k-means算法基本步骤:
(1) 从 n个数据对象任意选择 k 个对象作为初始聚类中心;
(2) 根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;
(3) 重新计算每个(有变化)聚类的均值(中心对象);
(4) 计算标准测度函数,当满足一定条件,如函数收敛时,则算法终止;如果条件不满足则回到步骤(2),不断重复直到标准测度函数开始收敛为止。(一般都采用均方差作为标准测度函数。)
三,k-means算法的java实现:
一共有七个类,General.java代表武将对象, Distance.java距离类计算各个武将到中心武将之间的距离, Cluster.java聚类对象包含一个中心武将和该聚类中所有武将, Kmeans.java核心的聚类算法类, Tool.java工具类用于转换武将的星级为数字等操作, TestKmeans.java测试类即入口文件, DomParser.java用于读取xml中的681个武将。
具体思路:先从general.xml文件中读取681个武将,然后随机选取初始类中心,计算各个武将到中心武将的距离,根据最小的距离进行聚类,然后重新根据平均值新的聚类的类中心,重新计算各个武将到新的中心武将的距离,直到更新后的聚类与原来的聚类包含的武将不再改变,即收敛时结束。
具体代码如下:
1,General.java
packagekmeans;
publicclassGeneral{
privateStringname;//姓名
privateintrender;//星级
privateinttongshai;//统帅
privateintwuli;//武力
privateintzhili;//智力
privateintpolic;//政治
privateintqiangbin;//枪兵
privateintjibin;//戟兵
privateintnubin;//弩兵
privateintqibin;//骑兵
privateintbinqi;//兵器
privateinttongwu;//统武
privateinttongzhi;//统智
privateinttongwuzhi;//统武智
privateinttongwuzhizheng;//统武智政
privateintsalary;//50级工资
publicGeneral(intrender,Stringname,inttongshai,intwuli,intzhili,
intpolic,intqiangbin,intjibin,intnubin,intqibin,
intbinqi,inttongwu,inttongzhi,inttongwuzhi,
inttongwuzhizheng,intsalary){
super();
this.name=name;
this.render=render;
this.tongshai=tongshai;
this.wuli=wuli;
this.zhili=zhili;
this.polic=polic;
this.qiangbin=qiangbin;
this.jibin=jibin;
this.nubin=nubin;
this.qibin=qibin;
this.binqi=binqi;
this.tongwu=tongwu;
this.tongzhi=tongzhi;
this.tongwuzhi=tongwuzhi;
this.tongwuzhizheng=tongwuzhizheng;
this.salary=salary;
}
publicGeneral(intrender,inttongshai,intwuli,intzhili,intpolic,
intqiangbin,intjibin,intnubin,intqibin,intbinqi,
inttongwu,inttongzhi,inttongwuzhi,inttongwuzhizheng,
intsalary){
super();
this.name="聚类中心";
this.render=render;
this.tongshai=tongshai;
this.wuli=wuli;
this.zhili=zhili;
this.polic=polic;
this.qiangbin=qiangbin;
this.jibin=jibin;
this.nubin=nubin;
this.qibin=qibin;
this.binqi=binqi;
this.tongwu=tongwu;
this.tongzhi=tongzhi;
this.tongwuzhi=tongwuzhi;
this.tongwuzhizheng=tongwuzhizheng;
this.salary=salary;
}
publicGeneral(){
}
@Override
publicStringtoString(){
return"武将[name="+name+",render="+Tool.dxingji(render)
+",tongshai="+tongshai+",wuli="+wuli+",zhili="
+zhili+",polic="+polic+",qiangbin="
+Tool.dchange(qiangbin)+",jibin="+Tool.dchange(jibin)
+",nubin="+Tool.dchange(nubin)+",qibin="
+Tool.dchange(qibin)+",binqi="+Tool.dchange(binqi)
+",tongwu="+tongwu+",tongzhi="+tongzhi
+",tongwuzhi="+tongwuzhi+",tongwuzhizheng="
+tongwuzhizheng+",salary="+salary+"]";
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintgetRender(){
returnrender;
}
publicvoidsetRender(intrender){
this.render=render;
}
publicintgetTongshai(){
returntongshai;
}
publicvoidsetTongshai(inttongshai){
this.tongshai=tongshai;
}
publicintgetWuli(){
returnwuli;
}
publicvoidsetWuli(intwuli){
this.wuli=wuli;
}
publicintgetZhili(){
returnzhili;
}
publicvoidsetZhili(intzhili){
this.zhili=zhili;
}
publicintgetPolic(){
returnpolic;
}
publicvoidsetPolic(intpolic){
this.polic=polic;
}
publicintgetQiangbin(){
returnqiangbin;
}
publicvoidsetQiangbin(intqiangbin){
this.qiangbin=qiangbin;
}
publicintgetJibin(){
returnjibin;
}
publicvoidsetJibin(intjibin){
this.jibin=jibin;
}
publicintgetNubin(){
returnnubin;
}
publicvoidsetNubin(intnubin){
this.nubin=nubin;
}
publicintgetQibin(){
returnqibin;
}
publicvoidsetQibin(intqibin){
this.qibin=qibin;
}
publicintgetBinqi(){
returnbinqi;
}
publicvoidsetBinqi(intbinqi){
this.binqi=binqi;
}
publicintgetTongwu(){
returntongwu;
}
publicvoidsetTongwu(inttongwu){
this.tongwu=tongwu;
}
publicintgetTongzhi(){
returntongzhi;
}
publicvoidsetTongzhi(inttongzhi){
this.tongzhi=tongzhi;
}
publicintgetTongwuzhi(){
returntongwuzhi;
}
publicvoidsetTongwuzhi(inttongwuzhi){
this.tongwuzhi=tongwuzhi;
}
publicintgetTongwuzhizheng(){
returntongwuzhizheng;
}
publicvoidsetTongwuzhizheng(inttongwuzhizheng){
this.tongwuzhizheng=tongwuzhizheng;
}
publicintgetSalary(){
returnsalary;
}
publicvoidsetSalary(intsalary){
this.salary=salary;
}
}
2,Distance.java
packagekmeans;
/**
*这个类用于计算距离的。。
*
*/
publicclassDistance{
intdest;//目的
intsource;//源
doubledist;//欧式距离
publicintgetDest(){
returndest;
}
publicvoidsetDest(intdest){
this.dest=dest;
}
publicintgetSource(){
returnsource;
}
publicvoidsetSource(intsource){
this.source=source;
}
publicdoublegetDist(){
returndist;
}
publicvoidsetDist(doubledist){
this.dist=dist;
}
/**
*计算源和目的的距离
*@paramdest目的武将
*@paramsource源武将
*@paramdist两者间的距离
*/
publicDistance(intdest,intsource,doubledist){
this.dest=dest;
this.source=source;
this.dist=dist;
}
publicDistance(){
}
}
3,Cluster.java
packagekmeans;
importjava.util.ArrayList;
publicclassCluster{
privateintcenter;//聚类中心武将的id
privateArrayListofCluster=newArrayList();//属于这个聚类的武将的集合
publicintgetCenter(){
returncenter;
}
publicvoidsetCenter(intcenter){
this.center=center;
}
publicArrayListgetOfCluster(){
returnofCluster;
}
publicvoidsetOfCluster(ArrayListofCluster){
this.ofCluster=ofCluster;
}
publicvoidaddGeneral(Generalgeneral){
if(!(this.ofCluster.contains(general)))
this.ofCluster.add(general);
}
}
4,Kmeans.java
packagekmeans;
importjava.util.*;
publicclassKmeans{
publicArrayListallGenerals=null;
publicinttotalNumber=0;//得到所有的武将数目
publicintK=0;//假设K=10
publicKmeans(){
allGenerals=newDomParser().prepare();
totalNumber=allGenerals.size();
K=3;
}
//第一次随机选取聚类中心
publicSetfirstRandom(){
Setcenter=newHashSet();//聚类中心的点的id,采用set保证不会有重复id
Randomran=newRandom();
introll=ran.nextInt(totalNumber);
while(center.size()
roll=ran.nextInt(totalNumber);
center.add(roll);
}
returncenter;
}
//根据聚类中心初始化聚类信息
publicArrayListinit(Setcenter){
ArrayListcluster=newArrayList();//聚类的数组
Iteratorit=center.iterator();
while(it.hasNext()){
Clusterc=newCluster();//代表一个聚类
c.setCenter(it.next());
cluster.add(c);
}
returncluster;
}
/**
*计算各个武将到各个聚类中心的距离,重新聚类
*
*@paramcluster
*聚类数组,用来聚类的,根据最近原则把武将聚类
*@paramcenter
*中心点id,用于计算各个武将到中心点的距离returncluster聚类后的所有聚类组成的数组
*/
publicArrayListjuLei(Setcenter,
ArrayListcluster){
ArrayListdistence=newArrayList();//存放距离信息,表示每个点到各个中心点的距离组成的数组
Generalsource=null;
Generaldest=null;
intid=0;//目的节点id
intid2=0;//源节点id
Object[]p=center.toArray();//p为聚类中心点id数组
booleanflag=false;
//分别计算各个点到各个中心点的距离,并将距离最小的加入到各个聚类中,进行聚类
for(inti=0;i
//每个点计算完,并聚类到距离最小的聚类中就清空距离数组
distence.clear();
//计算到j个类中心点的距离,便利各个中心点
for(intj=0;j
//如果该点不在中心点内则计算距离
if(!(center.contains(i))){
flag=true;
//计算距离
source=allGenerals.get(i);//某个点
dest=allGenerals.get((Integer)p[j]);//各个中心点
//计算距离并存入数组
distence.add(newDistance((Integer)p[j],i,Tool.juli(
source,dest)));
}else{
flag=false;
}
}
//说明计算完某个武将到类中心的距离,开始比较
if(flag==true){
//排序比较一个点到各个中心的距离的大小,找到距离最小的武将的目的id,和源id,
//目的id即类中心点id,这个就归到这个中心点所在聚类中
doublemin=distence.get(0).getDist();//默认第一个distance距离是最小的
//从1开始遍历distance数组
intminid=0;
for(intk=1;k
if(min>distence.get(k).getDist()){
min=distence.get(k).getDist();
id=distence.get(k).getDest();//目的,即类中心点
id2=distence.get(k).getSource();//某个武将
minid=k;
}else{
id=distence.get(minid).getDest();
id2=distence.get(minid).getSource();
}
}
//遍历cluster聚类数组,找到类中心点id与最小距离目的武将id相同的聚类
for(intn=0;n
//如果和中心点的id相同则setError
if(cluster.get(n).getCenter()==id){
cluster.get(n).addGeneral(allGenerals.get(id2));//将与该聚类中心距离最小的武将加入该聚类
break;
}
}
}
}
returncluster;
}
//产生新的聚类中心点数组
publicSetupdateCenter(){
Setcenter=newHashSet();
for(inti=0;i
center.add(i);
}
returncenter;
}
//更新聚类中心,求平均值
publicArrayListupdateCluster(ArrayListcluster){
ArrayListresult=newArrayList();
//重新产生的新的聚类中心组成的数组
//k个聚类进行更新聚类中心
for(intj=0;j
ArrayListps=cluster.get(j).getOfCluster();//该聚类的所有武将
//组成的数组
ps.add(allGenerals.get(cluster.get(j).getCenter()));//同时将该类中心对应的武将加入该武将数组
intsize=ps.size();//该聚类的长度大小
//计算和,然后在计算平均值
intsumrender=0,sumtongshai=0,sumwuli=0,sumzhili=0,sumjibin=0,sumnubin=0,sumqibin=0,sumpolic=0,sumqiangbin=0,sumbinqi=0,sumtongwu=0,sumtongzhi=0,sumtongwuzhi=0,sumtongwuzhizheng=0,sumsalary=0;
for(intk1=0;k1
sumrender+=ps.get(k1).getRender();
sumtongshai+=ps.get(k1).getRender();
sumwuli+=ps.get(k1).getWuli();
sumzhili+=ps.get(k1).getZhili();
sumjibin+=ps.get(k1).getJibin();
sumnubin+=ps.get(k1).getNubin();
sumqibin+=ps.get(k1).getQibin();
sumpolic+=ps.get(k1).getPolic();
sumqiangbin+=ps.get(k1).getQiangbin();
sumbinqi+=ps.get(k1).getBinqi();
sumtongwu+=ps.get(k1).getTongwu();
sumtongzhi+=ps.get(k1).getTongzhi();
sumtongwuzhi+=ps.get(k1).getTongwuzhi();
sumtongwuzhizheng+=ps.get(k1).getTongwuzhizheng();
sumsalary+=ps.get(k1).getSalary();
}
//产生新的聚类,然后加入到聚类数组中
ClusternewCluster=newCluster();
newCluster.setCenter(j);
//计算平均值并构造新的武将对象
newCluster.addGeneral(newGeneral(sumrender/size,sumtongshai
/size,sumwuli/size,sumzhili/size,sumjibin/size,
sumnubin/size,sumqibin/size,sumpolic=0,
sumqiangbin=0,sumbinqi/size,sumtongwu/size,
sumtongzhi/size,sumtongwuzhi/size,sumtongwuzhizheng
/size,sumsalary/size));
result.add(newCluster);
}
returnresult;
}
/**
*计算各个武将到各个更新后的聚类中心的距离,重新聚类
*@paramupdate更新后的聚类中心
*@paramcluster要存储的聚类中心
*/
publicArrayListupdateJuLei(ArrayListupdate,
ArrayListcluster){
ArrayListdistence=newArrayList();//存放距离信息,表示每个点到各个中心点的距离组成的数组
Generalsource=null;
Generaldest=null;
intid=0;//目的节点id
intid2=0;//源节点id
//Object[]p=center.toArray();//p为聚类中心点id数组
booleanflag=false;
//分别计算各个点到各个中心点的距离,并将距离最小的加入到各个聚类中,进行聚类
for(inti=0;i
//每个点计算完,并聚类到距离最小的聚类中就清空距离数组
distence.clear();
//计算到j个类中心点的距离,便利各个中心点
//for(intj=0;j
for(intj=0;j
//如果该点不在中心点内则计算距离
//if(!(center.contains(i))){
flag=true;
//计算距离
source=allGenerals.get(i);//某个点
//dest=allGenerals.get((Integer)p[j]);//各个中心点
dest=update.get(j).getOfCluster().get(0);//各个中心点
//计算距离并存入数组
//distence.add(newDistance((Integer)p[j],i,Tool.juli(
distence.add(newDistance(update.get(j).getCenter(),i,Tool.juli(
source,dest)));
/*}else{
flag=false;
}*/
}
//说明计算完某个武将到类中心的距离,开始比较
if(flag==true){
//排序比较一个点到各个中心的距离的大小,找到距离最小的武将的目的id,和源id,
//目的id即类中心点id,这个就归到这个中心点所在聚类中
doublemin=distence.get(0).getDist();//默认第一个distance距离是最小的
//从1开始遍历distance数组
intmid=0;
for(intk=1;k
if(min>distence.get(k).getDist()){
min=distence.get(k).getDist();
id=distence.get(k).getDest();//目的,即类中心点
id2=distence.get(k).getSource();//某个武将
mid=k;
}else{
id=distence.get(mid).getDest();
id2=distence.get(mid).getSource();
}
}
//遍历cluster聚类数组,找到类中心点id与最小距离目的武将id相同的聚类
for(intn=0;n
//如果和中心点的id相同则setError
if(cluster.get(n).getCenter()==id){
cluster.get(n).addGeneral(allGenerals.get(id2));//将与该聚类中心距离最小的武将加入该聚类
}
}
}
}
returncluster;
}
//不断循环聚类直到各个聚类没有重新分配
publicArrayListgetResult(){
ArrayListresult=newArrayList();
ArrayListtemp=newArrayList();
booleanflag=false;
//得到随机中心点然后进行聚类
Setcenter=firstRandom();
result=juLei(center,init(center));
print(result);
do{
//重新聚类
ArrayListup=updateCluster(result);//新的聚类中心
ArrayListcluster=init(updateCenter());//得到更新后的中心点对应的聚类数组
temp=updateJuLei(up,cluster);
//print(temp);
flag=isEquals(temp,result);
result=temp;
}while(!flag);
returnresult;
}
publicbooleanisEquals(ArrayListtemp,ArrayListresult){
booleanflag=false;
if(temp.size()!=result.size()){
returnflag;
}
for(Clustertem:temp){
for(Clusterres:result){
if(tem.getCenter()==res.getCenter()){
flag=true;
}
}
//如果找了一轮没找到则说明两个聚类
if(flag==false){
returnfalse;
}else{//如果找了一轮找到了,那么接着找
flag=false;
}
}
//如果代码能进行到这边,说明是true
flag=true;
returnflag;
}
//输出所有的聚类
publicvoidprint(ArrayListcs){
System.out.println("***************************************");
for(inti=0;i
Clusterc=cs.get(i);
System.out.println("-----------------------------------------------------");
System.out.println("center:"+allGenerals.get(c.getCenter()));
ArrayListp=c.getOfCluster();
for(intj=0;j
System.out.println("general:"+p.get(j)+"\n");
}
}
}
}
5,Tool.java
packagekmeans;
publicclassTool{
//将各种武器的精通程度转为数字
publicstaticintchange(Stringstr){
intresult=str.equals("精")?4:(str.equals("神")?3:(str
.equals("通")?2:1));
returnresult;
}
//将星级转为数字
publicstaticintxingji(Stringstr){
intresult=str.equals("★★★★★")?5:(str.equals("★★★★")?4:(str
.equals("★★★")?3:(str.equals("★★")?2:1)));
returnresult;
}
//反转将各种武器的数字转为精通程度
publicstaticStringdchange(intstr){
Stringresult=str==4?"精":(str==3?"神":(str==2?"通":"疏"));
returnresult;
}
//反转将数字转为星级
publicstaticStringdxingji(intstr){
Stringresult=str==5?"★★★★★":(str==4?"★★★★":(str==3?"★★★":(str==2?"★★":"★")));
returnresult;
}
//计算欧式距离传入两个将军对象。。
publicstaticdoublejuli(Generalg1,Generalg2){
doubleresult=(Double)Math.sqrt(StrictMath.pow(g1.getRender()-g2.getRender(),2)
+StrictMath.pow(g1.getTongshai()-g2.getTongshai(),2)
+StrictMath.pow(g1.getWuli()-g2.getWuli(),2)
+StrictMath.pow(g1.getZhili()-g2.getZhili(),2)
+StrictMath.pow(g1.getPolic()-g2.getPolic(),2)
+StrictMath.pow(g1.getQiangbin()-g2.getQiangbin(),2)
+StrictMath.pow(g1.getQibin()-g2.getQibin(),2)
+StrictMath.pow(g1.getJibin()-g2.getJibin(),2)
+StrictMath.pow(g1.getNubin()-g2.getNubin(),2)
+StrictMath.pow(g1.getBinqi()-g2.getBinqi(),2)
+StrictMath.pow(g1.getTongwu()-g2.getTongwu(),2)
+StrictMath.pow(g1.getTongzhi()-g2.getTongzhi(),2)
+StrictMath.pow(g1.getTongwuzhizheng()-g2.getTongwuzhizheng(),2)
+StrictMath.pow(g1.getTongwuzhi()-g2.getTongwuzhi(),2)
+StrictMath.pow(g1.getSalary()-g2.getSalary(),2)
);
returnresult;
}
}
6,DomParser.java
packagekmeans;
importjavax.xml.parsers.*;
importjava.io.*;
importjava.util.ArrayList;
importorg.w3c.dom.*;
importorg.xml.sax.SAXException;
publicclassDomParser{
privateArrayListgenerals=newArrayList();
publicArrayListprepare(){
//getdom解析器工厂
DocumentBuilderFactoryfactory=DocumentBuilderFactory.newInstance();
factory.setIgnoringElementContentWhitespace(true);
//getdom解析器
DocumentBuilderbuilder=null;
try{
builder=factory.newDocumentBuilder();
}catch(ParserConfigurationExceptione){
e.printStackTrace();
}
//解析文档
Documentdoc=null;
try{
doc=builder.parse(newFile("general.xml"));
}catch(SAXExceptione){
e.printStackTrace();
}catch(IOExceptione){
e.printStackTrace();
}
//取得根节点
ElementgeneralList=doc.getDocumentElement();
//得到所有row节点
NodeListnodeList=generalList.getElementsByTagName("Row");
//便利所有row节点
for(inti=1;i
System.out.println("------------the"+i
+"element--------------");
Noderow=nodeList.item(i);
//取得所有Data数据
NodeListattList=row.getChildNodes();
//取得数据中的各个部分,并加入ArrayList中
generals.add(newGeneral(Tool.xingji(attList.item(1)
.getTextContent()),attList.item(3).getTextContent(),
Integer.parseInt(attList.item(5).getTextContent()),
Integer.parseInt(attList.item(7).getTextContent()),
Integer.parseInt(attList.item(9).getTextContent()),
Integer.parseInt(attList.item(11).getTextContent()),
Tool.change(attList.item(13).getTextContent()),
Tool.change(attList.item(15).getTextContent()),
Tool.change(attList.item(17).getTextContent()),
Tool.change(attList.item(19).getTextContent()),
Tool.change(attList.item(21).getTextContent()),
Integer.parseInt(attList.item(23).getTextContent()),
Integer.parseInt(attList.item(25).getTextContent()),
Integer.parseInt(attList.item(27).getTextContent()),
Integer.parseInt(attList.item(29).getTextContent()),
Integer.parseInt(attList.item(31).getTextContent())));
System.out.println("星级:"
+Tool.xingji(attList.item(1).getTextContent())+"姓名:"
+attList.item(3).getTextContent()+"统率:"
+attList.item(5).getTextContent()+"武力:"
+attList.item(7).getTextContent()+"智力:"
+attList.item(9).getTextContent()+"政治:"
+attList.item(11).getTextContent()+"枪兵:"
+Tool.change(attList.item(13).getTextContent())+"戟兵:"
+Tool.change(attList.item(15).getTextContent())+"弩兵:"
+Tool.change(attList.item(17).getTextContent())+"骑兵:"
+Tool.change(attList.item(19).getTextContent())+"兵器:"
+Tool.change(attList.item(21).getTextContent())+"统武:"
+attList.item(23).getTextContent()+"统智:"
+attList.item(25).getTextContent()+"统武智:"
+attList.item(27).getTextContent()+"统武智政:"
+attList.item(29).getTextContent()+"50级工资:"
+attList.item(31).getTextContent()+"");
/*
*for(intj=0;j
*System.out.println(attList.item(j).getTextContent());}
*/
}
returngenerals;
}
}
7,TestKmeans.java
packagekmeans;
publicclassTestKmeans{
publicstaticvoidmain(String[]args){
Kmeans_eoldkmeans=newKmeans_eold();
kmeans.print(kmeans.getResult());
}
}
附部分general.xml:
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="/TR/REC-html40">
-09-13T11:21:51Z
-04-26T13:39:57Z
14.00
5850
11070
0
90
False
False
x:FullRows="1"ss:DefaultColumnWidth="54"ss:DefaultRowHeight="13.5">
星级
姓名
统率
武力
智力
政治
枪兵
戟兵
弩兵
骑兵
兵器
统武
统智
统武智
统武智政
50级工资
★★★★★
吕布
87
100
26
13
精
神
神
神
疏
161
194
257
350
19250
★★★★★
张飞
85
98
30
22
神
神
疏
精
疏
168
193
264
350
19250
★★★★★
関羽
95
97
75
62
神
神
通
精
疏
165
191
260
347
19085
★★★★★
马超
88
97
44
26
精
通
疏
神
通
168
187
259
353
19415
★★★★★
赵雲
91
96
76
65
神
通
神
神
疏
192
170
267
329
18095
★★★★★
许褚
65
96
36
20
精
通
疏
通
疏
161
101
197
217
11935
★★★★★
典韦
56
95
35
29
通
精
疏
疏
疏
151
91
186
215
11825
★★★★★
甘宁
86
94
76
18
神
精
精
精
神
181
183
270
351
19305
★★★★★
庞德
80
94
70
44
通
精
精
神
通
174
150
244
288
15840
★★★★★
文醜
78
94
25
25
精
通
精
神
疏
172
103
197
222
12210
★★★★★
黄忠
86
93
60
52
通
神
神
精
疏
185
171
263
321
17655
★★★★★
太史慈
82
93
66
58
精
神
疏
神
疏
175
148
241
299
16445
★★★★★
颜良
79
93
42
32
精
精
疏
神
疏
172
121
214
246
13530
★★★★★
张辽
93
92
78
58
神
神
通
神
通
183
167
257
330
18150
★★★★★
孙策
92
92
69
70
神
精
通
神
精
130
192
230
325
17875
★★★★★
魏延
81
92
69
49
精
神
通
精
疏
173
150
242
291
16005
★★★★★
华雄
81
92
56
40
通
通
疏
神
疏
173
137
229
269
14795
最终运行结果截图如下:
读取到得武将数据如图,
运行后的部分截图:
【编辑推荐】
【责任编辑:小林 TEL:(010)68476606】
点赞 0
如果觉得《java如何做聚类分析_K-means算法的Java实现 聚类分析681个三国武将》对你有帮助,请点赞、收藏,并留下你的观点哦!