聚类算法之MST算法 java实现版本

来源:互联网 发布:java经典书籍分享 编辑:程序博客网 时间:2024/05/21 10:08
 在介绍最小生成树算法(MST)之前,简单说一下平均链接算法(average-link)的实现过程,平均链接聚类算法和单链接类似,多了计算聚类之间距离矩阵的步骤 
   实现步骤如下: 
    

         
  • 1,将元素各成一组,把这些组放入容器H     
  • 2,循环元素距离数组,根据两层下标得到将要比较的两个元素A,B     
  • 3,在H中分别查找含有A,B的组AH,BH。假如AH不等于BH(也就是A,B不同组),  AH和BH的距离累加A,B的距离。     
  • 4,得到组间距离数组后,循环比较组间距离与阀值,小于阀值,则此两组合并成一组,合并之前把H中的两个作为比较的原始组删除。   
        

   MST算法比较有意思点,不仅用于聚类,还可以解决最短铺路成本这类问题。 
   我们假设一个场景:现在想在多个城市之间铺网络,怎样才是最短距离?每个城市当作一个数据点,每个点间的距离称为一个边,最短距离实际上就是求得每个点都能连成边,但是又不会回路的情况。 
   实现过程如下: 
  1,首先建立城市类和边类,如下 
 
Java代码  收藏代码
  1. /** 
  2.  * 城市 
  3.  *  
  4.  * @author duyf 
  5.  *  
  6.  */  
  7. class City {  
  8.   
  9.     private String name;  
  10.     // 经度  
  11.     private double x;  
  12.   
  13.     // 纬度  
  14.     private double y;  
  15.   
  16.     public double getX() {  
  17.         return x;  
  18.     }  
  19.   
  20.     public void setX(double x) {  
  21.         this.x = x;  
  22.     }  
  23.   
  24.     public double getY() {  
  25.         return y;  
  26.     }  
  27.   
  28.     public void setY(double y) {  
  29.         this.y = y;  
  30.     }  
  31.   
  32.     public String getName() {  
  33.         return name;  
  34.     }  
  35.   
  36.     public void setName(String name) {  
  37.         this.name = name;  
  38.     }  
  39.   
  40.     public boolean equals(Object obj) {  
  41.         if (obj == null) {  
  42.             return false;  
  43.         }  
  44.         if (this == obj) {  
  45.             return true;  
  46.         }  
  47.         City other = (City) obj;  
  48.         if (this.getX() == other.getX() && this.getY() == other.getY()) {  
  49.             return true;  
  50.         }  
  51.         return false;  
  52.     }  
  53. }  
  54.   
  55. /** 
  56.  * 边距 包含两端数据点(城市)的索引 
  57.  * @author duyf 
  58.  * 
  59.  */  
  60. class Edge {  
  61.       
  62.     private int i;  
  63.     private int j;  
  64.     private double w;  
  65.   
  66.     Edge(int i, int j, double w) {  
  67.         this.i = i;  
  68.         this.j = j;  
  69.         this.w = w;  
  70.     }  
  71.   
  72.     public int getI() {  
  73.         return i;  
  74.     }  
  75.   
  76.     public int getJ() {  
  77.         return j;  
  78.     }  
  79.   
  80.     public double getW() {  
  81.         return w;  
  82.     }  
  83.   
  84. }  
  85.     


2,MST核心类,Edge类表示一个边的两点和距离, 
找最短距离的边的过程是:不断的纳入最短边,并且再根据这些已知的最短边的两端寻找最短边(md 这句话我也感觉绕口 但应该是最通俗的了) 


Java代码  收藏代码
  1. public class MST {  
  2.   
  3.     private List<City> data;  
  4.       
  5.     private double[][] ds;  
  6.       
  7.     public MST(List<City> data){  
  8.         this.data=data;  
  9.     }  
  10.       
  11.     public List<Edge> compute(){  
  12.         // 距离矩阵  
  13.         ds = new double[data.size()][data.size()];  
  14.   
  15.         for (int i = 0; i < data.size(); i++) {  
  16.             City city1 = data.get(i);  
  17.             for (int j = i + 1; j < data.size(); j++) {  
  18.                 City city2 = data.get(j);  
  19.                 ds[i][j] = getDistance(city1, city2);  
  20.                 // 矩阵 对称性  
  21.                 ds[j][i] = ds[i][j];  
  22.             }  
  23.             ds[i][i] = 0.0;  
  24.         }     
  25.   
  26.         boolean[] isMst=new boolean[data.size()];  
  27.         isMst[0]=true;  
  28.         Edge edge=null;  
  29.         List<Edge> edges=new ArrayList<Edge>();  
  30.         while((edge=findMinEdge(isMst))!=null){  
  31.             edges.add(edge);      
  32.               
  33.             //标记为已知MST数据点  
  34.             isMst[edge.getJ()]=true;  
  35.         }  
  36.         return edges;  
  37.           
  38.     }  
  39.       
  40.     //找出 和 已知的MST数据点 最小距离的点  
  41.     private Edge findMinEdge(boolean[] isMst){  
  42.         //初始化无限大  
  43.         double minds = Double.POSITIVE_INFINITY;  
  44.         int minI=-1;  
  45.         int minJ=-1;  
  46.         Edge edge=null;  
  47.         for(int i=0;i<ds.length;i++){  
  48.             if(isMst[i]==true){  
  49.                 for(int j=0;j<ds.length;j++){  
  50.                     if(isMst[j]==false){  
  51.                         if(minds>ds[i][j]){  
  52.                             minds=ds[i][j];  
  53.                             minI=i;  
  54.                             minJ=j;  
  55.                         }  
  56.                     }  
  57.                 }  
  58.             }  
  59.         }  
  60.         if(minI>-1){  
  61.             edge=new Edge(minI,minJ,minds);  
  62.         }  
  63.         return edge;  
  64.     }  
  65.       
  66.     // 计算空间距离  
  67.     private double getDistance(City city1, City city2) {  
  68.          double  distance=Math.pow(city1.getX()-city2.getX(),2)+Math.pow(city1.getY()-city2.getY(),2);  
  69.          return Math.sqrt(distance);  
  70.            
  71.     }  
  72.       
  73.       
  74. }  


第一步肯定是算出临近距离矩阵 

3,测试一下 
Java代码  收藏代码
  1. public static void main(String[] args) {  
  2.         List<City> citys = new ArrayList<City>();  
  3.   
  4.         City city0 = new City();  
  5.         city0.setName("北 京");  
  6.         city0.setX(116.28);  
  7.         city0.setY(39.54);  
  8.         citys.add(city0);  
  9.           
  10.         City city1 = new City();  
  11.         city1.setName("上 海");  
  12.         city1.setX(121.29);  
  13.         city1.setY(31.14);  
  14.         citys.add(city1);  
  15.   
  16.         City city2 = new City();  
  17.         city2.setName("天 津");  
  18.         city2.setX(117.11);  
  19.         city2.setY(39.09);  
  20.         citys.add(city2);  
  21.   
  22.         City city3 = new City();  
  23.         city3.setName("重 庆");  
  24.         city3.setX(106.32);  
  25.         city3.setY(29.32);  
  26.         citys.add(city3);  
  27.   
  28.         City city4 = new City();  
  29.         city4.setName("哈尔滨");  
  30.         city4.setX(126.41);  
  31.         city4.setY(45.45);  
  32.         citys.add(city4);  
  33.   
  34.         City city5 = new City();  
  35.         city5.setName("长 春");  
  36.         city5.setX(125.19);  
  37.         city5.setY(43.52);  
  38.         citys.add(city5);  
  39.   
  40.         City city6 = new City();  
  41.         city6.setName("南 京");  
  42.         city6.setX(118.50);  
  43.         city6.setY(32.02);  
  44.         citys.add(city6);  
  45.   
  46.         City city7 = new City();  
  47.         city7.setName("武 汉");  
  48.         city7.setX(114.21);  
  49.         city7.setY(30.37);  
  50.         citys.add(city7);  
  51.   
  52.         City city8 = new City();  
  53.         city8.setName("台 北");  
  54.         city8.setX(121.31);  
  55.         city8.setY(25.03);  
  56.         citys.add(city8);  
  57.   
  58.         City city9 = new City();  
  59.         city9.setName("香 港");  
  60.         city9.setX(114.10);  
  61.         city9.setY(22.18);  
  62.         citys.add(city9);  
  63.           
  64.         MST mst=new MST(citys);  
  65.         List<Edge> edges=mst.compute();  
  66.           
  67.         System.out.println("------------------线路最佳方案如下------------------");  
  68.         for(Edge edge:edges){  
  69.             City from=citys.get(edge.getI());  
  70.             City to=citys.get(edge.getJ());  
  71.             double length=edge.getW();  
  72.             System.out.println(edge.getI()+"========>"+edge.getJ());  
  73.             System.out.println(from.getName()+"到"+to.getName()+",全长"+length);  
  74.         }  
  75.   
  76.     }  


 

By 阿飞哥 转载请说明 
腾讯微博:http://t.qq.com/duyunfeiRoom 
新浪微博:http://weibo.com/u/1766094735
0 0
原创粉丝点击