图的最小生成树(java实现)
1.图的最小生成树(贪心算法)
我两个算法的输出都是数组表示的,当前的索引值和当前索引对应的数据就是通路,比如parent[2] = 5;即2和5之间有一个通路,第二个可能比较好理解,第一个有点混乱
是什么?
将一个有权图中的 所有顶点 都连接起来,并保证连接的边的 总权重最小,即最小生成树,最小生成树不唯一
为什么?
传入邻接矩阵,返回可以生成最小生成树的数据
我们有两种方式生成图的最小生成树1.普里姆(Prim)算法2.克鲁斯卡尔(Kruskal)算法
怎样做?
图片参考博客:https://blog.csdn.net/afei__/article/details/83316587
下面是普里姆算法的最小生成树
下面是克鲁斯卡尔算法的最小生成树:
图的邻接矩阵表示法(无向图,上三角矩阵)
int[][] arr = new int[][]{
{-1, 4, 0, 0, 0, 0, 0, 8, 0},
{0, -1, 8, 0, 0, 0, 0, 11, 0},
{0, 0, -1, 7, 0, 4, 0, 0, 2},
{0, 0, 0, -1, 9, 14, 0, 0, 0},
{0, 0, 0, 0, -1, 10, 0, 0, 0},
{0, 0, 0, 0, 0, -1, 2, 0, 0},
{0, 0, 0, 0, 0, 0, -1, 1, 6},
{0, 0, 0, 0, 0, 0, 0, -1, 7},
{0, 0, 0, 0, 0, 0, 0, 0, -1}
};
1.普里姆算法(加点法)
需求:求出最小生成树的权值
输入参数:二维数组arr(邻接矩阵),列表list(存放已经被加入的点),整型sum(存放权值)
输出参数:整型数组parent
1)先找一个起点,这个起点为任意一点,放入list中 2)如果list中不包含全部节点,进入循环 1>遍历list中节点,查找不存在list中的邻接节点的最小值,记录下begin和end 2>将begin和end放入数组中,较小值节点赋值给较大值所在数组位置
3)返回parent
实现:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; /**
* 普里姆(Prim)算法
*
* @author Xiong YuSong
* 2019/3/22 16:02
*/
public class Prim { public static void main(String[] args) {
int[][] arr = new int[][]{
{-1, 4, 0, 0, 0, 0, 0, 8, 0},
{0, -1, 8, 0, 0, 0, 0, 11, 0},
{0, 0, -1, 7, 0, 4, 0, 0, 2},
{0, 0, 0, -1, 9, 14, 0, 0, 0},
{0, 0, 0, 0, -1, 10, 0, 0, 0},
{0, 0, 0, 0, 0, -1, 2, 0, 0},
{0, 0, 0, 0, 0, 0, -1, 1, 6},
{0, 0, 0, 0, 0, 0, 0, -1, 7},
{0, 0, 0, 0, 0, 0, 0, 0, -1}
};
List<Integer> list = new ArrayList<>();
//先将0放置在list中
list.add(0);
int begin = 0, end = 0, weight;
int[] parent = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
parent[i] = -1;
}
while (list.size() < arr.length) {
weight = Integer.MAX_VALUE;
for (Integer row : list) {
for (int i = 0; i < arr.length; i++) {
if (!list.contains(i)) {
if (i >= row + 1) {
if (arr[row][i] > 0 && arr[row][i] < weight) {
begin = row;
end = i;
weight = arr[row][i];
}
} else if (i <= row - 1) {
//我这里只用了上三角矩阵,所以这里需要画蛇添足写这一部分
if (arr[i][row] > 0 && arr[i][row] < weight) {
begin = row;
end = i;
weight = arr[i][row];
}
}
}
}
}
list.add(end);
parent[end] = begin;
}
System.out.println(Arrays.toString(parent));
}
}
2.克鲁斯卡尔算法(加边法)
需求:求出最小生成树的权值
构建类:Edge<begin,end,weight>三元组,根据weight(权值)排序
输入参数:存放有Edge的列表list,并查集parent
输出参数:并查集parent(最小生成树的数组表现形式)
原理:贪心算法的实现,程序中使用了并查集(判断两个集合中是否存在相同的数据)这种特殊的数据结构,使用数组实现
1)创建一个三元组<起始点,终止点,权值>,将邻接矩阵中数据放入三元组中,再放入list中,根据权值进行排序 2)创建变量count=0,整型数组parent 3)如果list中还存在值,则进行循环 1>判断begin和end是否存在于不同的集合中(判断是否在同一棵树中,即判断当前节点在并查集parent中的根节点是否为同一个) 2>如果存在不同的集合中,则将较小值节点赋值给较大值所在数组位置,较小值节点为较大值节点的父节点 4)返回parent
实现:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List; /**
* @author Xiong YuSong
* 2019/3/22 17:04
*/
class Edge implements Comparable<Edge> {
//起始点
private int begin;
//终止点
private int end;
//权值
private int weight; public Edge(int begin, int end, int weight) {
this.begin = begin;
this.end = end;
this.weight = weight;
} public int getBegin() {
return begin;
} public void setBegin(int begin) {
this.begin = begin;
} public int getEnd() {
return end;
} public void setEnd(int end) {
this.end = end;
} public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
} @Override
public int compareTo(Edge o) {
if (o.weight > this.weight) {
return -1;
} else {
return 1;
}
}
} public class Kruskal { public static void main(String[] args) {
//默认以a为根节点的最小生成树
List<Edge> list = new ArrayList<>();
int[][] arr = new int[][]{
{-1, 4, 0, 0, 0, 0, 0, 8, 0},
{0, -1, 8, 0, 0, 0, 0, 11, 0},
{0, 0, -1, 7, 0, 4, 0, 0, 2},
{0, 0, 0, -1, 9, 14, 0, 0, 0},
{0, 0, 0, 0, -1, 10, 0, 0, 0},
{0, 0, 0, 0, 0, -1, 2, 0, 0},
{0, 0, 0, 0, 0, 0, -1, 1, 6},
{0, 0, 0, 0, 0, 0, 0, -1, 7},
{0, 0, 0, 0, 0, 0, 0, 0, -1}
};
for (int i = 0; i < arr.length; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[i][j] > 0) {
list.add(new Edge(i, j, arr[i][j]));
}
}
}
Collections.sort(list);
//数组中每一个节点都只知道他的父节点是什么,-1表示不存在父节点,0位置是根节点
int[] parent = new int[arr.length];
for (int i = 1; i < arr.length; i++) {
parent[i] = -1;
}
int m = 0, n = 0;
for (Edge edge : list) {
//寻找这两个点有没有相同的父节点
m = find(parent, edge.getBegin());
n = find(parent, edge.getEnd());
if (m != n && parent[edge.getEnd()]>0) {
parent[edge.getEnd()] = edge.getBegin();
}
}
System.out.println(Arrays.toString(parent));
} private static int find(int[] parent, int ch) {
while (parent[ch] > 0) {
ch = parent[ch];
}
return ch;
}
}
图的最小生成树(java实现)的更多相关文章
- 图的存储,搜索,遍历,广度优先算法和深度优先算法,最小生成树-Java实现
1)用邻接矩阵方式进行图的存储.如果一个图有n个节点,则可以用n*n的二维数组来存储图中的各个节点关系. 对上面图中各个节点分别编号,ABCDEF分别设置为012345.那么AB AC AD 关系可以 ...
- hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)
还是畅通工程 Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submis ...
- 三张图彻底了解Java中字符串的不变性
转载: 三张图彻底了解Java中字符串的不变性 定义一个字符串 String s = "abcd"; s中保存了string对象的引用.下面的箭头可以理解为"存储他的引用 ...
- PowerDesigner(八)-面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)(转)
面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...
- C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)
1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...
- "《算法导论》之‘图’":最小生成树(无向图)
本文主要参考自<算法>. 加权图是一种为每条边关联一个权值或是成本的图模型.这种图能够自然地表示许多应用.在一幅航空图中,边表示航线,权值则可以表示距离或是费用.在一幅电路图中,边表示导线 ...
- 无向带权图的最小生成树算法——Prim及Kruskal算法思路
边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...
- 八、面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)
面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...
- java基础思维导图,让java不再难懂
java基础思维导图,让java不再难懂 原文链接 https://my.oschina.net/u/3080373/blog/873056 最近看了一些文章的思维导图,发现思维导图真是个强大的工具 ...
随机推荐
- Hello TypeScript
⒈TypeScript简介 1.JavaScript的超集 2.支持ECMAScript6标准,并支持输出ECMAScript3/5/6标准的纯JavaScript代码 3.支持ECMAScript未 ...
- spark调优篇-oom 优化(汇总)
spark 之所以需要调优,一是代码执行效率低,二是经常 OOM 内存溢出 内存溢出无非两点: 1. Driver 内存不够 2. Executor 内存不够 Driver 内存不够无非两点: 1. ...
- PowerShell 反弹渗透技巧
Windows PowerShell 是一种命令行外壳程序和脚本环境,使命令行用户和脚本编写者可以利用 .NET Framework的强大功能,并且与现有的WSH保持向后兼容,因此它的脚本程序不仅能访 ...
- dl in image process
deep learning目前为止无论在分类还是检测上,都是整体的处理,而不会出现像sift这样的局部特征,这个问题或许如果能克服掉,能让检测效果更进一大步.
- hdu 6047
题解:先对b排序,用一个数组预处理a,记录当前位置之后到n的最大值,然后在用一个变量维护新增变量的最大值,用的时候和前面的数组的最大值做一个比较就ok. AC代码: #include <cstd ...
- idea插件,配置
1.插件 2.配置 1.去除double shift 全局搜索的功能,反正不符合我的习惯 Help -> Find Action 搜索 registry ,勾选 double.click.ha ...
- 3、详解 ESLint 规则 转自https://blog.csdn.net/bbsyi/article/details/88816637
什么是 ESLint ? ESLint 是在 ECMAScript/JavaScript 代码中识别和报告模式匹配的工具,它的目标是保证代码的一致性和避免错误.在许多方面,它和 JSLint.JSHi ...
- c++11 用户定义字面量
c++11 用户定义字面量 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inc ...
- java中的多态总结
一.多态的概述 ava作为面向对象的语言,同样可以描述一个事物的多种形态.如Student类继承了Person类,一个Student的对象便既是Student,又是Person. Java中多态的代码 ...
- 转 Git使用教程,最详细,最傻瓜,最浅显,真正手把手教
预警:因为详细,所以行文有些长,新手边看边操作效果出乎你的预料) 这个也不错 https://www.cnblogs.com/qcloud1001/p/9796750.html 一:Git是什么?Gi ...