Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 783|回复: 0

最小生成树的Kruskal算法(java)

[复制链接]

该用户从未签到

发表于 2011-9-18 13:27:07 | 显示全部楼层 |阅读模式

Kruskal算法在实现过程中的关键和难点在于:如何判断欲加入的一条边是否与生成树中已保留的边形成回路?

     我们可以将顶点划分到不同的集合中,每个集合中的顶点表示一个无回路的连通分量,很明显算法开始时,把所有n个顶点划分到n个集合中,每个集合只有一个顶点,表明顶点之间互不相通。当选取一条边时,若它的两个顶点分属于不同的集合,则表明此边连通了两个不同的连通分量,因每个连通分量无回路,所以连通后得到的连通分量仍不会产生回路,因此这条边应该保留,且把它们作为一个连通分量,即把它的两个顶点所在集合合并成一个集合。如果选取的一条边的两个顶点属于同一个集合,则此边应该舍弃,因为同一个集合中的顶点是连通无回路的,若再加入一条边则必然产生回路。


/*  
*日期:2010-04-18 20:02  
*开发者:heroyan  
*联系方式:zndxysf@126.com  
*功能:无向图最小生成树Kruskal算法实现案例  
*/  
import java.util.Scanner;   
import java.util.Arrays;   
import java.util.ArrayList;   
  
public class Kruskal{   
    private static int MAX = 100;   
    private ArrayList< Edge> edge = new ArrayList< Edge>();//整个图的边   
    private ArrayList< Edge> target = new ArrayList< Edge>();//目标边,最小生成树   
    private int[] parent = new int[MAX];//标志所在的集合   
    private static double INFINITY = 99999999.99;//定义无穷大   
    private double mincost = 0.0;//最小成本   
    private int n;//结点个数   
      
    public Kruskal(){}   
      
    public static void main(String args[]){   
        Kruskal sp = new Kruskal();   
        sp.init();   
        System.out.println(sp.kruskal());   
        sp.print();   
    }   
    //初始化   
    public void init(){   
        Scanner scan = new Scanner(System.in);   
        int p,q;   
        double w;   
           
        System.out.println("spanning tree begin!Input the node number:");   
        n = scan.nextInt();   
        System.out.println("Input the graph(-1,-1,-1 to exit)");   
           
        while(true){   
            p = scan.nextInt();   
            q = scan.nextInt();   
            w = scan.nextDouble();   
            if(p < 0 || q < 0 || w < 0){   
                break;   
            }   
            Edge e = new Edge();   
            e.start = p;   
            e.end = q;   
            e.cost = w;   
            edge.add(e);   
        }   
           
        mincost = 0.0;   
           
        for(int i = 1; i <= n; ++i){   
            parent = i;//将每个顶点初始化为一个集合,父节点指向自己。
        }   
    }   
    //集合合并,将父节点为j的改为父节点为k(父节点同为k的合并到一个集合。)
    public void union(int j, int k){   
        for(int i = 1; i <= n; ++i){   
            if(parent == j){   
                parent = k;   
            }   
        }   
    }   
    //prim算法主体   
    public double kruskal(){   
        //找剩下的n-2条边   
        int i = 0;   
        while(i < n-1 && edge.size() > 0){   
            //每次取一最小边,并删除   
            double min = INFINITY;   
            int tag = 0;   
            Edge tmp = null;   
            for(int j = 0; j < edge.size(); ++j){   
                Edge tt = edge.get(j);   
                if(tt.cost < min){   
                    min = tt.cost;   
                    tmp = tt;   
                }   
            }   
            int jj = parent[tmp.start];   
            int kk = parent[tmp.end];   
            //去掉环   
            if(jj != kk){   
                ++i;   
                target.add(tmp);   
                mincost += tmp.cost;   
                union(jj,kk);   
            }   
            edge.remove(tmp);   
        }   
        if(i != n-1){   
            System.out.println("no spanning tree");
             return 0;
        }   
      return mincost;
    }   
    //打印结果   
    public void print(){   
        for(int i = 0; i < target.size(); ++i){   
            Edge e = target.get(i);   
            System.out.println("the " + (i+1) + "th edge:" + e.start + "---" + e.end);   
        }   
    }   
}   
  
class Edge   
{   
    public int start;//始边   
    public int end;//终边   
    public double cost;//权重   
}

运行:
C:\work>java Kruskal
spanning tree begin!Input the node number:
5
Input the graph(-1,-1,-1 to exit)
1 2 2
2 5 9
2 3 8
5 4 7
4 1 10
1 3 12
3 4 6
3 5 3
-1 -1 -1
19.0
the 1th edge:1---2
the 2th edge:3---5
the 3th edge:3---4
the 4th edge:2---3
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

GMT+8, 2024-6-7 06:17 , Processed in 0.374786 second(s), 46 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表