在介绍最小生成树算法(MST)之前,简单说一下平均链接算法(average-link)的实现过程,平均链接聚类算法和单链接类似,多了计算聚类之间距离矩阵的步骤
实现步骤如下:
MST算法比较有意思点,不仅用于聚类,还可以解决最短铺路成本这类问题。
我们假设一个场景:现在想在多个城市之间铺网络,怎样才是最短距离?每个城市当作一个数据点,每个点间的距离称为一个边,最短距离实际上就是求得每个点都能连成边,但是又不会回路的情况。
实现过程如下:
1,首先建立城市类和边类,如下
2,MST核心类,Edge类表示一个边的两点和距离,
找最短距离的边的过程是:不断的纳入最短边,并且再根据这些已知的最短边的两端寻找最短边(md 这句话我也感觉绕口 但应该是最通俗的了)
第一步肯定是算出临近距离矩阵
3,测试一下
By 阿飞哥 转载请说明
腾讯微博: http://t.qq.com/duyunfeiRoom
新浪微博: http://weibo.com/u/1766094735
实现步骤如下:
- 1,将元素各成一组,把这些组放入容器H
- 2,循环元素距离数组,根据两层下标得到将要比较的两个元素A,B
- 3,在H中分别查找含有A,B的组AH,BH。假如AH不等于BH(也就是A,B不同组), AH和BH的距离累加A,B的距离。
- 4,得到组间距离数组后,循环比较组间距离与阀值,小于阀值,则此两组合并成一组,合并之前把H中的两个作为比较的原始组删除。
MST算法比较有意思点,不仅用于聚类,还可以解决最短铺路成本这类问题。
我们假设一个场景:现在想在多个城市之间铺网络,怎样才是最短距离?每个城市当作一个数据点,每个点间的距离称为一个边,最短距离实际上就是求得每个点都能连成边,但是又不会回路的情况。
实现过程如下:
1,首先建立城市类和边类,如下
- /**
- * 城市
- *
- * @author duyf
- *
- */
- class City {
- private String name;
- // 经度
- private double x;
- // 纬度
- private double y;
- public double getX() {
- return x;
- }
- public void setX(double x) {
- this.x = x;
- }
- public double getY() {
- return y;
- }
- public void setY(double y) {
- this.y = y;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public boolean equals(Object obj) {
- if (obj == null) {
- return false;
- }
- if (this == obj) {
- return true;
- }
- City other = (City) obj;
- if (this.getX() == other.getX() && this.getY() == other.getY()) {
- return true;
- }
- return false;
- }
- }
- /**
- * 边距 包含两端数据点(城市)的索引
- * @author duyf
- *
- */
- class Edge {
- private int i;
- private int j;
- private double w;
- Edge(int i, int j, double w) {
- this.i = i;
- this.j = j;
- this.w = w;
- }
- public int getI() {
- return i;
- }
- public int getJ() {
- return j;
- }
- public double getW() {
- return w;
- }
- }
2,MST核心类,Edge类表示一个边的两点和距离,
找最短距离的边的过程是:不断的纳入最短边,并且再根据这些已知的最短边的两端寻找最短边(md 这句话我也感觉绕口 但应该是最通俗的了)
- public class MST {
- private List<City> data;
- private double[][] ds;
- public MST(List<City> data){
- this.data=data;
- }
- public List<Edge> compute(){
- // 距离矩阵
- ds = new double[data.size()][data.size()];
- for (int i = 0; i < data.size(); i++) {
- City city1 = data.get(i);
- for (int j = i + 1; j < data.size(); j++) {
- City city2 = data.get(j);
- ds[i][j] = getDistance(city1, city2);
- // 矩阵 对称性
- ds[j][i] = ds[i][j];
- }
- ds[i][i] = 0.0;
- }
- boolean[] isMst=new boolean[data.size()];
- isMst[0]=true;
- Edge edge=null;
- List<Edge> edges=new ArrayList<Edge>();
- while((edge=findMinEdge(isMst))!=null){
- edges.add(edge);
- //标记为已知MST数据点
- isMst[edge.getJ()]=true;
- }
- return edges;
- }
- //找出 和 已知的MST数据点 最小距离的点
- private Edge findMinEdge(boolean[] isMst){
- //初始化无限大
- double minds = Double.POSITIVE_INFINITY;
- int minI=-1;
- int minJ=-1;
- Edge edge=null;
- for(int i=0;i<ds.length;i++){
- if(isMst[i]==true){
- for(int j=0;j<ds.length;j++){
- if(isMst[j]==false){
- if(minds>ds[i][j]){
- minds=ds[i][j];
- minI=i;
- minJ=j;
- }
- }
- }
- }
- }
- if(minI>-1){
- edge=new Edge(minI,minJ,minds);
- }
- return edge;
- }
- // 计算空间距离
- private double getDistance(City city1, City city2) {
- double distance=Math.pow(city1.getX()-city2.getX(),2)+Math.pow(city1.getY()-city2.getY(),2);
- return Math.sqrt(distance);
- }
- }
第一步肯定是算出临近距离矩阵
3,测试一下
- public static void main(String[] args) {
- List<City> citys = new ArrayList<City>();
- City city0 = new City();
- city0.setName("北 京");
- city0.setX(116.28);
- city0.setY(39.54);
- citys.add(city0);
- City city1 = new City();
- city1.setName("上 海");
- city1.setX(121.29);
- city1.setY(31.14);
- citys.add(city1);
- City city2 = new City();
- city2.setName("天 津");
- city2.setX(117.11);
- city2.setY(39.09);
- citys.add(city2);
- City city3 = new City();
- city3.setName("重 庆");
- city3.setX(106.32);
- city3.setY(29.32);
- citys.add(city3);
- City city4 = new City();
- city4.setName("哈尔滨");
- city4.setX(126.41);
- city4.setY(45.45);
- citys.add(city4);
- City city5 = new City();
- city5.setName("长 春");
- city5.setX(125.19);
- city5.setY(43.52);
- citys.add(city5);
- City city6 = new City();
- city6.setName("南 京");
- city6.setX(118.50);
- city6.setY(32.02);
- citys.add(city6);
- City city7 = new City();
- city7.setName("武 汉");
- city7.setX(114.21);
- city7.setY(30.37);
- citys.add(city7);
- City city8 = new City();
- city8.setName("台 北");
- city8.setX(121.31);
- city8.setY(25.03);
- citys.add(city8);
- City city9 = new City();
- city9.setName("香 港");
- city9.setX(114.10);
- city9.setY(22.18);
- citys.add(city9);
- MST mst=new MST(citys);
- List<Edge> edges=mst.compute();
- System.out.println("------------------线路最佳方案如下------------------");
- for(Edge edge:edges){
- City from=citys.get(edge.getI());
- City to=citys.get(edge.getJ());
- double length=edge.getW();
- System.out.println(edge.getI()+"========>"+edge.getJ());
- System.out.println(from.getName()+"到"+to.getName()+",全长"+length);
- }
- }
By 阿飞哥 转载请说明
腾讯微博: http://t.qq.com/duyunfeiRoom
新浪微博: http://weibo.com/u/1766094735