达内LOGO和北京达内网址达内科技培训项目:Java培训 3G培训 Android培训 软件测试培训北京达内服务电话
java培训
JAVA培训:K-means算法的Java实现 聚类分析681个三国武将(2)

3,Cluster.java
1. </pre><pre name="code" class="java">package kmeans; 
2. 
3. import java.util.ArrayList; 
4. 
5. public class Cluster { 
6.     private int center;// 聚类中心武将的id 
7.     private ArrayList<General> ofCluster = new ArrayList<General>();// 属于这个聚类的武将的集合 
8. 
9.     public int getCenter() { 
10.         return center; 
11.     } 
12. 
13.     public void setCenter(int center) { 
14.         this.center = center; 
15.     } 
16. 
17.     public ArrayList<General> getOfCluster() { 
18.         return ofCluster; 
19.     } 
20. 
21.     public void setOfCluster(ArrayList<General> ofCluster) { 
22.         this.ofCluster = ofCluster; 
23.     } 
24. 
25.     public void addGeneral(General general) { 
26.         if (!(this.ofCluster.contains(general))) 
27.             this.ofCluster.add(general); 
28.     } 
29. } 
4,Kmeans.java
1. </pre><pre name="code" class="java">
1. package kmeans; 
2. 
3. import java.util.*; 
4. 
5. public class Kmeans { 
6.     public ArrayList<General> allGenerals = null; 
7.     public int totalNumber = 0;// 得到所有的武将数目 
8.     public int K = 0;// 假设K=10 
9. 
10.     public Kmeans() { 
11.         allGenerals = new DomParser().prepare(); 
12.         totalNumber = allGenerals.size(); 
13.         K = 3; 
14.     } 
15. 
16.     // 第一次随机选取聚类中心 
17.     public Set<Integer> firstRandom() { 
18.         Set<Integer> center = new HashSet<Integer>();// 聚类中心的点的id,采用set保证不会有重复id 
19.         Random ran = new Random(); 
20.         int roll = ran.nextInt(totalNumber); 
21.         while (center.size() < K) { 
22.             roll = ran.nextInt(totalNumber); 
23.             center.add(roll); 
24.         } 
25.         return center; 
26.     } 
27. 
28.     // 根据聚类中心初始化聚类信息 
29.     public ArrayList<Cluster> init(Set<Integer> center) { 
30.         ArrayList<Cluster> cluster = new ArrayList<Cluster>();// 聚类 的数组 
31.         Iterator<Integer> it = center.iterator(); 
32.         while (it.hasNext()) { 
33.             Cluster c = new Cluster();// 代表一个聚类 
34.             c.setCenter(it.next()); 
35.             cluster.add(c); 
36.         } 
37.         return cluster; 
38.     } 
39. 
40.     /** 
41.      * 计算各个武将到各个聚类中心的距离,重新聚类 
42.      *  
43.      * @param cluster 
44.      *            聚类数组,用来聚类的,根据最近原则把武将聚类 
45.      * @param center 
46.      *            中心点id,用于计算各个武将到中心点的距离 return cluster 聚类后的所有聚类组成的数组 
47.      */
48.     public ArrayList<Cluster> juLei(Set<Integer> center, 
49.             ArrayList<Cluster> cluster) { 
50.         ArrayList<Distance> distence = new ArrayList<Distance>();// 存放距离信息,表示每个点到各个中心点的距离组成的数组 
51.         General source = null; 
52.         General dest = null; 
53.         int id = 0;// 目的节点id 
54.         int id2 = 0;// 源节点id 
55.         Object[] p = center.toArray();// p 为聚类中心点id数组 
56.         boolean flag = false; 
57.         // 分别计算各个点到各个中心点的距离,并将距离最小的加入到各个聚类中,进行聚类 
58.         for (int i = 0; i < totalNumber; i++) { 
59.             // 每个点计算完,并聚类到距离最小的聚类中就清空距离数组 
60.             distence.clear(); 
61.             // 计算到j个类中心点的距离,便利各个中心点 
62.             for (int j = 0; j < center.size(); j++) { 
63.                 // 如果该点不在中心点内 则计算距离 
64.                 if (!(center.contains(i))) { 
65.                     flag = true; 
66.                     // 计算距离 
67.                     source = allGenerals.get(i);// 某个点 
68.                     dest = allGenerals.get((Integer) p[j]);// 各个 中心点 
69.                     // 计算距离并存入数组 
70.                     distence.add(new Distance((Integer) p[j], i, Tool.juli( 
71.                             source, dest))); 
72.                 } else { 
73.                     flag = false; 
74.                 } 
75.             } 
76.             // 说明计算完某个武将到类中心的距离,开始比较 
77.             if (flag == true) { 
78.                 // 排序比较一个点到各个中心的距离的大小,找到距离最小的武将的 目的id,和源id, 
79.                 // 目的id即类中心点id,这个就归到这个中心点所在聚类中 
80.                 double min = distence.get(0).getDist();// 默认第一个distance距离是最小的 
81.                 // 从1开始遍历distance数组 
82.                 int minid = 0; 
83.                 for (int k = 1; k < distence.size(); k++) { 
84.                     if (min > distence.get(k).getDist()) { 
85.                         min = distence.get(k).getDist(); 
86.                         id = distence.get(k).getDest();// 目的,即类中心点 
87.                         id2 = distence.get(k).getSource();// 某个武将 
88.                         minid = k; 
89.                     } else { 
90.                         id = distence.get(minid).getDest(); 
91.                         id2 = distence.get(minid).getSource(); 
92.                     } 
93.                 } 
94.                 // 遍历cluster聚类数组,找到类中心点id与最小距离目的武将id相同的聚类 
95.                 for (int n = 0; n < cluster.size(); n++) { 
96.                     // 如果和中心点的id相同 则setError 
97.                     if (cluster.get(n).getCenter() == id) { 
98.                         cluster.get(n).addGeneral(allGenerals.get(id2));// 将与该聚类中心距离最小的武将加入该聚类 
99.                         break; 
100.                     } 
101.                 } 
102.             } 
103.         } 
104.         return cluster; 
105.     } 
106. 
107.     // 产生新的聚类中心点数组 
108.     public Set<Integer> updateCenter() { 
109.         Set<Integer> center = new HashSet<Integer>(); 
110.         for (int i = 0; i < K; i++) { 
111.             center.add(i); 
112.         } 
113.         return center; 
114.     } 
115. 
116.     // 更新聚类中心, 求平均值 
117.     public ArrayList<Cluster> updateCluster(ArrayList<Cluster> cluster) { 
118.         ArrayList<Cluster> result = new ArrayList<Cluster>(); 
119.         // 重新产生的新的聚类中心组成的数组 
120.         // k个聚类进行更新聚类中心 
121.         for (int j = 0; j < K; j++) { 
122.             ArrayList<General> ps = cluster.get(j).getOfCluster();// 该聚类的所有 武将 
123.                                                                     // 组成的数组 
124.             ps.add(allGenerals.get(cluster.get(j).getCenter()));// 同时将该类中心对应的武将加入该武将数组 
125.             int size = ps.size();// 该聚类的长度大小 
126.             // 计算和,然后在计算平均值 
127.             int sumrender = 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; 
128.             for (int k1 = 0; k1 < size; k1++) { 
129.                 sumrender += ps.get(k1).getRender(); 
130.                 sumtongshai += ps.get(k1).getRender(); 
131.                 sumwuli += ps.get(k1).getWuli(); 
132.                 sumzhili += ps.get(k1).getZhili(); 
133.                 sumjibin += ps.get(k1).getJibin(); 
134.                 sumnubin += ps.get(k1).getNubin(); 
135.                 sumqibin += ps.get(k1).getQibin(); 
136.                 sumpolic += ps.get(k1).getPolic(); 
137.                 sumqiangbin += ps.get(k1).getQiangbin(); 
138.                 sumbinqi += ps.get(k1).getBinqi(); 
139.                 sumtongwu += ps.get(k1).getTongwu(); 
140.                 sumtongzhi += ps.get(k1).getTongzhi(); 
141.                 sumtongwuzhi += ps.get(k1).getTongwuzhi(); 
142.                 sumtongwuzhizheng += ps.get(k1).getTongwuzhizheng(); 
143.                 sumsalary += ps.get(k1).getSalary(); 
144.             } 
145.             // 产生新的聚类,然后加入到聚类数组中 
146.             Cluster newCluster = new Cluster(); 
147.             newCluster.setCenter(j); 
148.             // 计算平均值并构造新的武将对象 
149.             newCluster.addGeneral(new General(sumrender / size, sumtongshai 
150.                     / size, sumwuli / size, sumzhili / size, sumjibin / size, 
151.                     sumnubin / size, sumqibin / size, sumpolic = 0, 
152.                     sumqiangbin = 0, sumbinqi / size, sumtongwu / size, 
153.                     sumtongzhi / size, sumtongwuzhi / size, sumtongwuzhizheng 
154.                             / size, sumsalary / size)); 
155.             result.add(newCluster); 
156.         } 
157.         return result; 
158. 
159.     } 
160. 
161.     /** 
162.      * 计算各个武将到各个更新后的聚类中心的距离,重新聚类 
163.      * @param update 更新后的聚类中心 
164.      * @param cluster 要存储的聚类中心 
165.      */
166.     public ArrayList<Cluster> updateJuLei(ArrayList<Cluster> update, 
167.             ArrayList<Cluster> cluster) { 
168.         ArrayList<Distance> distence = new ArrayList<Distance>();// 存放距离信息,表示每个点到各个中心点的距离组成的数组 
169.         General source = null; 
170.         General dest = null; 
171.         int id = 0;// 目的节点id 
172.         int id2 = 0;// 源节点id 
173.         //Object[] p = center.toArray();// p 为聚类中心点id数组 
174.         boolean flag = false; 
175.         // 分别计算各个点到各个中心点的距离,并将距离最小的加入到各个聚类中,进行聚类 
176.         for (int i = 0; i < totalNumber; i++) { 
177.             // 每个点计算完,并聚类到距离最小的聚类中就清空距离数组 
178.             distence.clear(); 
179.             // 计算到j个类中心点的距离,便利各个中心点 
180.             //for (int j = 0; j < center.size(); j++) { 
181.             for (int j = 0; j < update.size(); j++) { 
182.                 // 如果该点不在中心点内 则计算距离 
183.                 //if (!(center.contains(i))) { 
184.                     flag = true; 
185.                     // 计算距离 
186.                     source = allGenerals.get(i);// 某个点 
187.                     // dest = allGenerals.get((Integer) p[j]);// 各个 中心点 
188.                     dest = update.get(j).getOfCluster().get(0);// 各个 中心点 
189.                     // 计算距离并存入数组 
190.                     //distence.add(new Distance((Integer) p[j], i, Tool.juli( 
191.                     distence.add(new Distance(update.get(j).getCenter(), i, Tool.juli( 
192.                             source, dest))); 
193.                     /*} else { 
194.                     flag = false; 
195.                 }*/
196.             } 
197.             // 说明计算完某个武将到类中心的距离,开始比较 
198.             if (flag == true) { 
199.                 // 排序比较一个点到各个中心的距离的大小,找到距离最小的武将的 目的id,和源id, 
200.                 // 目的id即类中心点id,这个就归到这个中心点所在聚类中 
201.                 double min = distence.get(0).getDist();// 默认第一个distance距离是最小的 
202.                 // 从1开始遍历distance数组 
203.                 int mid = 0; 
204.                 for (int k = 1; k < distence.size(); k++) { 
205.                     if (min > distence.get(k).getDist()) { 
206.                         min = distence.get(k).getDist(); 
207.                         id = distence.get(k).getDest();// 目的,即类中心点 
208.                         id2 = distence.get(k).getSource();// 某个武将 
209.                         mid = k; 
210.                     } else { 
211.                         id = distence.get(mid).getDest(); 
212.                         id2 = distence.get(mid).getSource(); 
213.                     } 
214.                 } 
215.                 // 遍历cluster聚类数组,找到类中心点id与最小距离目的武将id相同的聚类 
216.                 for (int n = 0; n < cluster.size(); n++) { 
217.                     // 如果和中心点的id相同 则setError 
218.                     if (cluster.get(n).getCenter() == id) { 
219.                         cluster.get(n).addGeneral(allGenerals.get(id2));// 将与该聚类中心距离最小的武将加入该聚类 
220.                     } 
221.                 } 
222.             } 
223.         } 
224.         return cluster; 
225.     } 
226. 
227.     // 不断循环聚类直到各个聚类没有重新分配 
228.     public ArrayList<Cluster> getResult() { 
229.         ArrayList<Cluster> result = new ArrayList<Cluster>(); 
230.         ArrayList<Cluster> temp = new ArrayList<Cluster>(); 
231.         boolean flag = false; 
232.         // 得到随机中心点然后进行聚类 
233.         Set<Integer> center = firstRandom(); 
234.         result = juLei(center, init(center)); 
235.         print(result); 
236.         do { 
237.             // 重新聚类 
238.             ArrayList<Cluster> up = updateCluster(result);//新的聚类中心 
239.             ArrayList<Cluster> cluster = init(updateCenter()); // 得到更新后的中心点对应的聚类数组 
240.             temp = updateJuLei(up, cluster); 
241.             //print(temp); 
242.             flag = isEquals(temp, result); 
243.             result = temp; 
244.         } while (!flag); 
245.         return result; 
246.     } 
247.      
248.     public boolean isEquals(ArrayList<Cluster> temp, ArrayList<Cluster> result){ 
249.         boolean flag = false; 
250.         if(temp.size() != result.size()){ 
251.             return flag; 
252.         } 
253.         for(Cluster tem : temp){ 
254.             for(Cluster res : result){ 
255.                 if(tem.getCenter() == res.getCenter()){ 
256.                     flag = true; 
257.                 } 
258.             } 
259.             // 如果找了一轮没找到 则说明两个聚类 
260.             if(flag == false){ 
261.                 return false; 
262.             }else{// 如果找了一轮找到了,那么接着找 
263.                 flag = false; 
264.             } 
265.         } 
266.         //如果代码能进行到这边,说明是true 
267.         flag = true; 
268.         return flag; 
269.     } 
270.      
271.     //输出所有的聚类 
272.     public void print(ArrayList<Cluster> cs) { 
273.         System.out.println("***************************************"); 
274.         for (int i = 0; i < cs.size(); i++) { 
275.             Cluster c = cs.get(i); 
276.             System.out.println("-----------------------------------------------------"); 
277.             System.out.println("center: " + allGenerals.get(c.getCenter())); 
278.             ArrayList<General> p = c.getOfCluster(); 
279.             for (int j = 0; j < p.size(); j++) { 
280.                 System.out.println("general:"+p.get(j)+"\n"); 
281.             } 
282.         } 
283.     } 
284. 
285. } 

 苏州达内

客服系统