zoukankan      html  css  js  c++  java
  • 图-最小生成树算法之Kruskal及其Java实现

    1.Kruskal算法

    Kruskal算法基于贪心,因此它追求的是近似最优解,也就是说由Kruskal得出的生成树并不一定是最优解。

    Kruskal算法求最小生成树的关键在于,每次选取图中权值最小(及贪心),并不会构成环的边,直到所有点都被囊括。一般,边的个数=点的个数-1。

    如下无向图:

    要找到最小生成树,克鲁斯卡尔算法的步骤如下:


    2.Java实现

    针对上述《算法导论》中的例子,有Java代码如下:

      1 import java.util.ArrayList;
      2 import java.util.Collections;
      3 import java.util.Iterator;
      4 
      5 //图类 无向图
      6 class G{
      7     ArrayList<V> vs=new ArrayList<V>();
      8     ArrayList<E> es=new ArrayList<E>();
      9     
     10     public void addV(V v) {
     11         vs.add(v);
     12     }
     13     
     14     public void add(E e) {
     15         es.add(e);
     16     }
     17 }
     18 
     19 //
     20 class V{
     21     String name;
     22     boolean isvisited=false;
     23     
     24     public V(String name) {
     25         this.name=name;
     26     }
     27 
     28     @Override
     29     public String toString() {
     30         return name;
     31     }
     32 }
     33 
     34 //
     35 class E{
     36     V v1;   //
     37     V v2;   //
     38     int Weight;   //权重
     39     boolean isvisited=false;
     40     
     41     public E(V v1,V v2,int Weight) {
     42         this.v1=v1;
     43         this.v2=v2;
     44         this.Weight=Weight;
     45     }
     46 
     47     @Override
     48     public String toString() {
     49         return "(" + v1 + ", " + v2 + ":" + Weight + ")";
     50     }
     51 }
     52 
     53 public class MinTree {
     54     //克鲁斯卡尔
     55     static void kruskal(G graph) {
     56         ArrayList<E> edges=graph.es;  //存储图的边集合
     57         ArrayList<E> forest=new ArrayList<E>();  //存放符合结果的边
     58         
     59         for(E e:edges) {   //遍历边集合,在初始化图的时候,边已按照权值排序
     60             ArrayList<E> testForest=refreshForest(forest);
     61             getEnd(testForest,e.v1,e.v2);
     62             if(endV) {  //判断是否形成回路
     63                 System.out.print(e);    //输出符合条件(不形成回路,权值最小)的边
     64                 forest.add(e);
     65             }
     66         }
     67     }
     68     
     69     //将图的边集合按权值排序
     70     static ArrayList<E> sortEdgeByWeight(ArrayList<E> es){
     71         for(int i=0;i<es.size();i++) {
     72             for(int j=0;j<es.size();j++) {
     73                 if(es.get(i).Weight<es.get(j).Weight) {
     74                     Collections.swap(es, i, j);
     75                 }
     76             }
     77         }
     78         return es;
     79     }
     80     
     81     static boolean endV=true;
     82     //判断新的边是否会和已有森林形成环:即得到目标点的末节点,由此判断两者是否相同,若相同则有环
     83     static void getEnd(ArrayList<E> testForest,V start,V end) {
     84         for(E e:testForest) {
     85             if(e.isvisited==false) {
     86                 if(e.v1.equals(start)) {
     87                     e.isvisited=true;
     88                     if(e.v2.equals(end)) {
     89                         endV=false;
     90                     }else {
     91                         getEnd(testForest,e.v2,end);
     92                     }
     93                 }else if (e.v2.equals(start)) {
     94                     e.isvisited=true;
     95                     if(e.v1.equals(end)) {
     96                         endV=false;
     97                     }else {
     98                         getEnd(testForest,e.v1,end);
     99                     }
    100                 }
    101             }
    102         }
    103     }
    104     
    105     //刷新森林:将森林中所有边标为未被查看,将endV标志也初始化一下
    106     static ArrayList<E> refreshForest(ArrayList<E> forest) {
    107         endV=true;
    108         for(E e:forest) {
    109             e.isvisited=false;
    110         }
    111         return forest;
    112     }
    113     
    114     public static void main(String[] args) {
    115         // TODO Auto-generated method stub
    116         //创建点
    117         V a=new V("a");
    118         V b=new V("b");
    119         V c=new V("c");
    120         V d=new V("d");
    121         V e=new V("e");
    122         V f=new V("f");
    123         V g=new V("g");
    124         V h=new V("h");
    125         V i=new V("i");
    126         //创建点
    127         
    128         //创建边
    129         E e0=new E(a,b,4);
    130         E e1=new E(a,h,8);
    131         E e2=new E(b,h,11);
    132         E e3=new E(b,c,8);
    133         E e4=new E(h,i,7);
    134         E e5=new E(h,g,1);
    135         E e6=new E(i,c,2);
    136         E e7=new E(i,g,6);
    137         E e8=new E(c,d,7);
    138         E e9=new E(c,f,4);
    139         E e10=new E(g,f,2);
    140         E e11=new E(d,f,14);
    141         E e12=new E(d,e,9);
    142         E e13=new E(f,e,10);
    143         //创建边
    144         
    145         //创建图
    146         G graph=new G();
    147         graph.addV(a);
    148         graph.addV(b);
    149         graph.addV(c);
    150         graph.addV(d);
    151         graph.addV(e);
    152         graph.addV(f);
    153         graph.addV(g);
    154         graph.addV(h);
    155         graph.addV(i);
    156         ArrayList<E> es=new ArrayList<E>();
    157         es.add(e0);
    158         es.add(e1);
    159         es.add(e2);
    160         es.add(e3);
    161         es.add(e4);
    162         es.add(e5);
    163         es.add(e6);
    164         es.add(e7);
    165         es.add(e8);
    166         es.add(e9);
    167         es.add(e10);
    168         es.add(e11);
    169         es.add(e12);
    170         es.add(e13);
    171         graph.es=sortEdgeByWeight(es);
    172         //创建图
    173         
    174         //输出图
    175         ArrayList<V> vertexs=graph.vs;
    176         ArrayList<E> edges=graph.es;
    177         Iterator iVertex=vertexs.iterator();
    178         Iterator iEdge=edges.iterator();
    179         System.out.println("点集合:");
    180         while(iVertex.hasNext()) {
    181             System.out.print(iVertex.next());
    182         }
    183         System.out.println();
    184         System.out.println("边集合:");
    185         while(iEdge.hasNext()) {
    186             System.out.print(iEdge.next());
    187         }
    188         //输出图
    189         
    190         //最小生成树
    191         //克鲁斯卡尔
    192         System.out.println("");
    193         System.out.println("克鲁斯卡尔:");
    194         kruskal(graph);
    195         //最小生成树
    196 
    197     }
    198 
    199 }

    输出:

  • 相关阅读:
    触屏时间控制
    小程序 坐标算距离 (copy)
    微信小程序 对接口常用
    conversion function to_char to_number
    南通
    日期 function
    数字 function
    字符串处理函数
    沪通铁路1
    NVL NVL2 COALESCE NULLIF decode
  • 原文地址:https://www.cnblogs.com/StrayLesley/p/10746736.html
Copyright © 2011-2022 走看看