图-最小生成树算法之Kruskal及其Java实现
1.Kruskal算法
Kruskal算法基于贪心,因此它追求的是近似最优解,也就是说由Kruskal得出的生成树并不一定是最优解。
Kruskal算法求最小生成树的关键在于,每次选取图中权值最小(及贪心),并不会构成环的边,直到所有点都被囊括。一般,边的个数=点的个数-1。
如下无向图:
要找到最小生成树,克鲁斯卡尔算法的步骤如下:
2.Java实现
针对上述《算法导论》中的例子,有Java代码如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; //图类 无向图
class G{
ArrayList<V> vs=new ArrayList<V>();
ArrayList<E> es=new ArrayList<E>(); public void addV(V v) {
vs.add(v);
} public void add(E e) {
es.add(e);
}
} //点
class V{
String name;
boolean isvisited=false; public V(String name) {
this.name=name;
} @Override
public String toString() {
return name;
}
} //边
class E{
V v1; //点
V v2; //点
int Weight; //权重
boolean isvisited=false; public E(V v1,V v2,int Weight) {
this.v1=v1;
this.v2=v2;
this.Weight=Weight;
} @Override
public String toString() {
return "(" + v1 + ", " + v2 + ":" + Weight + ")";
}
} public class MinTree {
//克鲁斯卡尔
static void kruskal(G graph) {
ArrayList<E> edges=graph.es; //存储图的边集合
ArrayList<E> forest=new ArrayList<E>(); //存放符合结果的边 for(E e:edges) { //遍历边集合,在初始化图的时候,边已按照权值排序
ArrayList<E> testForest=refreshForest(forest);
getEnd(testForest,e.v1,e.v2);
if(endV) { //判断是否形成回路
System.out.print(e); //输出符合条件(不形成回路,权值最小)的边
forest.add(e);
}
}
} //将图的边集合按权值排序
static ArrayList<E> sortEdgeByWeight(ArrayList<E> es){
for(int i=0;i<es.size();i++) {
for(int j=0;j<es.size();j++) {
if(es.get(i).Weight<es.get(j).Weight) {
Collections.swap(es, i, j);
}
}
}
return es;
} static boolean endV=true;
//判断新的边是否会和已有森林形成环:即得到目标点的末节点,由此判断两者是否相同,若相同则有环
static void getEnd(ArrayList<E> testForest,V start,V end) {
for(E e:testForest) {
if(e.isvisited==false) {
if(e.v1.equals(start)) {
e.isvisited=true;
if(e.v2.equals(end)) {
endV=false;
}else {
getEnd(testForest,e.v2,end);
}
}else if (e.v2.equals(start)) {
e.isvisited=true;
if(e.v1.equals(end)) {
endV=false;
}else {
getEnd(testForest,e.v1,end);
}
}
}
}
} //刷新森林:将森林中所有边标为未被查看,将endV标志也初始化一下
static ArrayList<E> refreshForest(ArrayList<E> forest) {
endV=true;
for(E e:forest) {
e.isvisited=false;
}
return forest;
} public static void main(String[] args) {
// TODO Auto-generated method stub
//创建点
V a=new V("a");
V b=new V("b");
V c=new V("c");
V d=new V("d");
V e=new V("e");
V f=new V("f");
V g=new V("g");
V h=new V("h");
V i=new V("i");
//创建点 //创建边
E e0=new E(a,b,4);
E e1=new E(a,h,8);
E e2=new E(b,h,11);
E e3=new E(b,c,8);
E e4=new E(h,i,7);
E e5=new E(h,g,1);
E e6=new E(i,c,2);
E e7=new E(i,g,6);
E e8=new E(c,d,7);
E e9=new E(c,f,4);
E e10=new E(g,f,2);
E e11=new E(d,f,14);
E e12=new E(d,e,9);
E e13=new E(f,e,10);
//创建边 //创建图
G graph=new G();
graph.addV(a);
graph.addV(b);
graph.addV(c);
graph.addV(d);
graph.addV(e);
graph.addV(f);
graph.addV(g);
graph.addV(h);
graph.addV(i);
ArrayList<E> es=new ArrayList<E>();
es.add(e0);
es.add(e1);
es.add(e2);
es.add(e3);
es.add(e4);
es.add(e5);
es.add(e6);
es.add(e7);
es.add(e8);
es.add(e9);
es.add(e10);
es.add(e11);
es.add(e12);
es.add(e13);
graph.es=sortEdgeByWeight(es);
//创建图 //输出图
ArrayList<V> vertexs=graph.vs;
ArrayList<E> edges=graph.es;
Iterator iVertex=vertexs.iterator();
Iterator iEdge=edges.iterator();
System.out.println("点集合:");
while(iVertex.hasNext()) {
System.out.print(iVertex.next());
}
System.out.println();
System.out.println("边集合:");
while(iEdge.hasNext()) {
System.out.print(iEdge.next());
}
//输出图 //最小生成树
//克鲁斯卡尔
System.out.println("");
System.out.println("克鲁斯卡尔:");
kruskal(graph);
//最小生成树 } }
输出:
图-最小生成树算法之Kruskal及其Java实现的更多相关文章
- 最小生成树算法 prim kruskal两种算法实现 HDU-1863 畅通工程
最小生成树 通俗解释:一个连通图,可将这个连通图删减任意条边,仍然保持连通图的状态并且所有边权值加起来的总和使其达到最小.这就是最小生成树 可以参考下图,便于理解 原来的图: 最小生成树(蓝色线): ...
- 最小生成树算法总结(Kruskal,Prim)
今天复习最小生成树算法. 最小生成树指的是在一个图中选择n-1条边将所有n个顶点连起来,且n-1条边的权值之和最小.形象一点说就是找出一条路线遍历完所有点,不能形成回路且总路程最短. Kurskal算 ...
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...
- 无向带权图的最小生成树算法——Prim及Kruskal算法思路
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
- 如何在 Java 中实现最小生成树算法
定义 在一幅无向图 \(G=(V,E)\) 中,\((u, v)\) 为连接顶点 \(u\) 和顶点 \(v\) 的边,\(w(u,v)\) 为边的权重,若存在边的子集 \(T\subseteq E\ ...
- Kruskal 最小生成树算法
对于一个给定的连通的无向图 G = (V, E),希望找到一个无回路的子集 T,T 是 E 的子集,它连接了所有的顶点,且其权值之和为最小. 因为 T 无回路且连接所有的顶点,所以它必然是一棵树,称为 ...
- java数据结构_笔记(5)_图的算法
图的算法 1 图的遍历图的遍历就是从图中某个顶点出发,按某种方法对图中所有顶点访问且仅访问一次.遍历算法是求解图的连通性问题.拓扑排序和求关键路径等算法的基础. 2 深度优先遍历从图中某个顶点V 出发 ...
- 最小生成树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind
最小支撑树树--Prim算法,基于优先队列的Prim算法,Kruskal算法,Boruvka算法,“等价类”UnionFind 最小支撑树树 前几节中介绍的算法都是针对无权图的,本节将介绍带权图的最小 ...
- 最小生成树算法(Prim,Kruskal)
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
随机推荐
- BZOJ4517:[SDOI2016]排列计数(组合数学,错排公式)
Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是 ...
- CF893F:Subtree Minimum Query(线段树合并)
Description 给你一颗有根树,点有权值,m次询问,每次问你某个点的子树中距离其不超过k的点的权值的最小值.(边权均为1,点权有可能重复,k值每次询问有可能不同,强制在线) Input 第一行 ...
- 「GXOI / GZOI2019」旅行者
题目 我还是太傻了 考虑每一条边的贡献,对于一条有向边\((u,v,w)\),我们求出\(k\)个关键点中到\(u\)最近的距离\(dis_1\),以及\(v\)到\(k\)个关键点中最近的距离\(d ...
- 第一章 进入java的世界
一.你要做的事情: 1. 编写源代码:xxx.java 2. 编译器编译:检测代码错误 3. 输出:编译器输出xxx.class 4. 运行:java虚拟机运行xxx.class
- YII缓存整理
缓存 缓存是用于提升网站性能的一种即简单又有效的途径.通过存储相对静态的数据至缓存以备所需,我们可以省去生成这些数据的时间.在 Yii 中使用缓存主要包括配置和访问缓存组件 . 如下的应用配置指定了一 ...
- 为什么会有object这么一个根基类
先问一个问题,为什么需要有一个统一的基类:Object?甚至,我们在编程语言中也常常见到这种模式,比如Java中的object.C#的object,甚至一些纯对象的脚本语言(Ruby里连数字123都是 ...
- webpack.config.js配置遇到Error: Cannot find module '@babel/core'问题
在webpack配置,将ES6转成ES5的时候,,出现Error: Cannot find module '@babel/core'错误最初以为是babel-core没有安装上.重装了好几遍babel ...
- django restframework 序列化
Serialization 序列化 创建表 from django.db import models from pygments.lexers import get_all_lexers from p ...
- C3P0与DBUtil配合实现DAO层的开发
写在前面:菜鸟拙见,望请纠正 一:为什么需要连接池 普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,需要数据库连 ...
- HBase--大数据系统的数据库方案
本文主要围绕以下三方面来讨论HBase:是什么.为什么.怎样做. 1. 什么是HBase HBase是一个开源的.分布式的.非关系型数据库,其设计思想来源于Google的Big Table.通过集群管 ...