避圈法(求最小生成树)java实现

一、避圈法解决的问题

避圈法(求最小生成树)java实现_第1张图片


上图是一个带有回路的简单带权图。即两点间可能不只有一种到达方式,且每条边都带有权值。

在实际生产环境中,可将此图看作是城市间线缆的建造成本,或者拼车时送达各乘客的路线成本。

而避圈法是为了在这种图的基础上,得到一条连接所有点,且总权值最小的图。

在《图论》中称作该图权重最小的最小生成树,如下图:

避圈法(求最小生成树)java实现_第2张图片


二、代码展示


测试类:

package mintree;

import java.util.List;

/**
 * @author sean22
 * @date 2018/1/30/030.
 */
public class Test {
    public static void main(String[] args) {
        int X = Kruskal.X;
        int[][] matrix = {
                {X,X,X,3,4,X},
                {X,X,2,X,5,X},
                {X,2,X,X,X,4},
                {3,X,X,X,X,2},
                {4,5,X,X,X,3},
                {X,X,4,2,3,X}
        };
        List lines = Kruskal.getASCLines(matrix);
        Kruskal.loadPath(lines,matrix);
        Kruskal.print(matrix);
    }
}

主要功能类:

package mintree;


import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * @author sean22
 * @date 2017/12/13/013.
 * 避圈法
 */
public class Kruskal {
    static int X = Integer.MAX_VALUE;

    public static List getASCLines(int[][] matrix){
        List lines = new LinkedList<>();
        for(int i=0;i lines,int[][] matrix){
        Path r = new Path();
        List exist = new LinkedList<>();
       for(int i=0;i

构造路径类:

package mintree;

import java.util.LinkedList;
import java.util.List;

/**
 * @author sean22
 * @date 2017/12/14/014.
 */
public class Path {
    List> nodes;
    Path(){
        nodes = new LinkedList<>();
    }

    /**
     * @param line
     * @return true 添加成功,false 形成回路,添加失败
     */
    public boolean add(Line line){
        int added =Integer.MAX_VALUE;
        for(int n=0;n node = nodes.get(n);
            boolean startEqual =false;
            boolean endEqual = false;
            for(int i=0;i list = new LinkedList<>();
            list.add(line.startPos);
            list.add(line.endPos);
            nodes.add(list);
        }
        return true;
    }
    /**
     * line若是桥,合并两个node
     */
    public void bindNodesIfBridge(List>nodes,int added,List node){
        if(added!=Integer.MAX_VALUE){
            nodes.get(added).addAll(node);
            nodes.remove(node);
        }
    }
}

线段对象:

package mintree;

/**
 * Created by sean on 2017/12/13/013.
 */
public class Line implements Comparable{
    int startPos;
    int endPos;
    int quality;
    Line(int startPos,int endPos,int quality){
        this.startPos = startPos;
        this.endPos = endPos;
        this.quality = quality;
    }

    @Override
    public String toString() {
        return "("+startPos+"<->"+endPos+"="+quality+")";
    }

    @Override
    public int compareTo(Line o) {
        return this.quality-o.quality;
    }
}


测试结果:

避圈法(求最小生成树)java实现_第3张图片


三、代码思想:

 1. 首先初始化邻接矩阵(矩阵中记录了点到点间的连接关系,其中X表示两点不可达。),将其转换为一个Line

对象的集合(舍弃不可达的路径)。


2.然后将线段在集合中升序排列。【按升序排列可以保证在添加一条线段形成回路时,这条线段在回路中总是权值最高的。

那么删掉该线段即可】。


3.依次读取线段,将出现以下四种情况:

 (1)Path的nodes中的所有数组均不包含当前线段的任意端点。

执行:nodes中新建一个数组,保存线段的两个端点。【即新建一条通路】

 (2)当前线段的一个端点已在nodes的某一个数组中,但另一个端点未在nodes中所有数组找到。

 执行:将未保存的另一个端点保存在存在端点的数组中。【在当前通路中添加一条线段】

  (3)当前线段的一个端点在nodes的某一个数组,另一个端点在nodes中的另一个数组。

 执行:合并两个数组。【当前线段作为桥连接起了两条通路】

 (4) 当前线段的两个端点都已经存在在同一个数组中。

 执行:舍弃当前线段。【形成了回路】


最终,若此图是一个连通图,一定可以将所有的通路通过(2)连接到一起,并避开所有回路,得到最小权值和的连通图。

你可能感兴趣的:(算法)