k-means聚类java实现

以前做项目时候写的代码,数据是一维的,多维的也一样,把距离计算的改一改就行int term = Math.abs(dotlist.get(centerIndex[j]).x- dotlist.get(i).x);


package uestc.dmlab.call;

import java.io.BufferedReader;
import java.io.FileReader;
import java.security.KeyStore.Entry;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

public class Clustering {

	/**
	 * 
	 * @param fileName
	 *            文件中每个字段对应一个概率
	 * @param k
	 *            聚成k个类
	 * @param minDistance
	 *            聚类中心位移小于minDistance时停止迭代
	 * @return
	 */
	public static HashMap<String, Integer> cluster(String fileName, int k,
			int minDistance) {
		try {
			BufferedReader br = new BufferedReader(new FileReader(fileName));
			List<Dot> dotlist = new LinkedList<Dot>();
			String line;
			int count = 0;// 行数
			while ((line = br.readLine()) != null) {
				String s[] = line.split(",");
				Dot dot = new Dot();
				dot.isCenter = false;
				dot.isVirtual = false;
				dot.name = s[0];
				// if(s.length<4){
				// System.out.println(line);
				// }
				dot.x = Integer.parseInt(s[3]);
				dotlist.add(dot);
				count++;
			}
			if (count < k) {
				k = count;
			}

			// 随机初始化k个聚类中心
			int centerIndex[] = new int[k]; // 存储k个中心点在dotlist中的索引
			int centerNum = k;
			while (centerNum > 0) {
				int index = new Random().nextInt(count);
				if (!dotlist.get(index).isCenter) {
					centerNum--;
					dotlist.get(index).isCenter = true;
					centerIndex[centerNum] = index;
				}
			}

			// K个聚类
			Cluster[] clusers = new Cluster[k];

			boolean flag = true;
			while (flag) {
				flag = false;
				clusers = new Cluster[k];
				for (int i = 0; i < clusers.length; i++) {
					clusers[i] = new Cluster();
				}
				//System.out.println(clusers.length);
				// 找到离第i个点最近的聚类中心
				for (int i = 0; i < dotlist.size(); i++) {
					// 该点不是中心点也不是虚拟点就计算它与所有中心点的距离并取最小值
					// if(!dotlist.get(i).isCenter&&!dotlist.get(i).isVirtual){
					if (!dotlist.get(i).isVirtual) {
						int distance = Integer.MAX_VALUE;
						int c = 0;// 记录离该节点最近的中心点的索引
						for (int j = 0; j < k; j++) {
							int term = Math.abs(dotlist.get(centerIndex[j]).x
									- dotlist.get(i).x);
							if (distance > term) {
								distance = term;
								c = j;
							}
						}
						clusers[c].dots.add(i);
					}
				}

				// 重新计算聚类中心
				for (int i = 0; i < k; i++) {
					Cluster cluster = clusers[i];

					if (cluster.dots.size() > 0) { //若该类中有点
						int sum = 0;
						for (int j = 0; j < cluster.dots.size(); j++) {
							sum += dotlist.get(cluster.dots.get(j)).x;
						}

						Dot dot = new Dot();
						dot.x = sum / cluster.dots.size();
						dot.isCenter = true;
						dot.isVirtual = true;

						// 新旧聚类中心的距离
						int term = Math.abs(dotlist.get(centerIndex[i]).x
								- dot.x);
						if (term > minDistance)
							flag = true;

						dotlist.add(dot);
						centerIndex[i] = dotlist.indexOf(dot); // 第i个聚类的中心改变
					}
				}
			}

			// 生成分类映射
			HashMap<String, Integer> map = new HashMap<String, Integer>();
			for (Dot dot : dotlist) {
				if (dot.isVirtual == false) {
					int className = -1;
					for (int i = 0; i < k; i++) {
						if (clusers[i].dots.contains(dotlist.indexOf(dot)))
							className = i;
					}
					map.put(dot.name, className);
				}
			}
			return map;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return new HashMap<String, Integer>();

	}

	public static void main(String[] args) {
		Map<String, Integer> map = Clustering.cluster(
				"C:/Documents and Settings/Administrator/桌面/123.txt", 2, 0);
	    Iterator<Map.Entry<String, Integer>> it = map.entrySet().iterator();
	    while(it.hasNext()){
	    	Map.Entry<String, Integer> entry = it.next();
	    	System.out.println(entry.getKey()+","+entry.getValue());
	    }

	}
}

class Dot {
	String name;
	int x;
	boolean isCenter;
	boolean isVirtual;
}

class Cluster {
	// 记录了该类中点的索引值
	LinkedList<Integer> dots = new LinkedList<Integer>();
}


  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值