1.图的最小生成树(贪心算法)

我两个算法的输出都是数组表示的,当前的索引值和当前索引对应的数据就是通路,比如parent[2] = 5;即2和5之间有一个通路,第二个可能比较好理解,第一个有点混乱

是什么?

将一个有权图中的 所有顶点 都连接起来,并保证连接的边的 总权重最小,即最小生成树,最小生成树不唯一

为什么?

传入邻接矩阵,返回可以生成最小生成树的数据

我们有两种方式生成图的最小生成树1.普里姆(Prim)算法2.克鲁斯卡尔(Kruskal)算法

怎样做?

图片参考博客:https://blog.csdn.net/afei__/article/details/83316587

下面是普里姆算法的最小生成树

下面是克鲁斯卡尔算法的最小生成树:

图的邻接矩阵表示法(无向图,上三角矩阵)

  1. 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. 1)先找一个起点,这个起点为任意一点,放入list
  2.  
  3. 2)如果list中不包含全部节点,进入循环
  4.  
  5.   1>遍历list中节点,查找不存在list中的邻接节点的最小值,记录下beginend
  6.  
  7.   2>将beginend放入数组中,较小值节点赋值给较大值所在数组位置
  1. 3)返回parent

实现:

  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.List;
  4.  
  5. /**
  6. * 普里姆(Prim)算法
  7. *
  8. * @author Xiong YuSong
  9. * 2019/3/22 16:02
  10. */
  11. public class Prim {
  12.  
  13. public static void main(String[] args) {
  14. int[][] arr = new int[][]{
  15. {-1, 4, 0, 0, 0, 0, 0, 8, 0},
  16. {0, -1, 8, 0, 0, 0, 0, 11, 0},
  17. {0, 0, -1, 7, 0, 4, 0, 0, 2},
  18. {0, 0, 0, -1, 9, 14, 0, 0, 0},
  19. {0, 0, 0, 0, -1, 10, 0, 0, 0},
  20. {0, 0, 0, 0, 0, -1, 2, 0, 0},
  21. {0, 0, 0, 0, 0, 0, -1, 1, 6},
  22. {0, 0, 0, 0, 0, 0, 0, -1, 7},
  23. {0, 0, 0, 0, 0, 0, 0, 0, -1}
  24. };
  25. List<Integer> list = new ArrayList<>();
  26. //先将0放置在list中
  27. list.add(0);
  28. int begin = 0, end = 0, weight;
  29. int[] parent = new int[arr.length];
  30. for (int i = 0; i < arr.length; i++) {
  31. parent[i] = -1;
  32. }
  33. while (list.size() < arr.length) {
  34. weight = Integer.MAX_VALUE;
  35. for (Integer row : list) {
  36. for (int i = 0; i < arr.length; i++) {
  37. if (!list.contains(i)) {
  38. if (i >= row + 1) {
  39. if (arr[row][i] > 0 && arr[row][i] < weight) {
  40. begin = row;
  41. end = i;
  42. weight = arr[row][i];
  43. }
  44. } else if (i <= row - 1) {
  45. //我这里只用了上三角矩阵,所以这里需要画蛇添足写这一部分
  46. if (arr[i][row] > 0 && arr[i][row] < weight) {
  47. begin = row;
  48. end = i;
  49. weight = arr[i][row];
  50. }
  51. }
  52. }
  53. }
  54. }
  55. list.add(end);
  56. parent[end] = begin;
  57. }
  58. System.out.println(Arrays.toString(parent));
  59. }
  60. }

2.克鲁斯卡尔算法(加边法)

需求:求出最小生成树的权值

构建类:Edge<begin,end,weight>三元组,根据weight(权值)排序

输入参数:存放有Edge的列表list,并查集parent

输出参数:并查集parent(最小生成树的数组表现形式)

原理:贪心算法的实现,程序中使用了并查集(判断两个集合中是否存在相同的数据)这种特殊的数据结构,使用数组实现

  1. 1)创建一个三元组<起始点,终止点,权值>,将邻接矩阵中数据放入三元组中,再放入list中,根据权值进行排序
  2.  
  3. 2)创建变量count=0,整型数组parent
  4.  
  5. 3)如果list中还存在值,则进行循环
  6.  
  7.   1>判断beginend是否存在于不同的集合中(判断是否在同一棵树中,即判断当前节点在并查集parent中的根节点是否为同一个)
  8.  
  9.   2>如果存在不同的集合中,则将较小值节点赋值给较大值所在数组位置,较小值节点为较大值节点的父节点
  10.  
  11. 4)返回parent

实现:

  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.Collections;
  4. import java.util.List;
  5.  
  6. /**
  7. * @author Xiong YuSong
  8. * 2019/3/22 17:04
  9. */
  10. class Edge implements Comparable<Edge> {
  11. //起始点
  12. private int begin;
  13. //终止点
  14. private int end;
  15. //权值
  16. private int weight;
  17.  
  18. public Edge(int begin, int end, int weight) {
  19. this.begin = begin;
  20. this.end = end;
  21. this.weight = weight;
  22. }
  23.  
  24. public int getBegin() {
  25. return begin;
  26. }
  27.  
  28. public void setBegin(int begin) {
  29. this.begin = begin;
  30. }
  31.  
  32. public int getEnd() {
  33. return end;
  34. }
  35.  
  36. public void setEnd(int end) {
  37. this.end = end;
  38. }
  39.  
  40. public int getWeight() {
  41. return weight;
  42. }
  43.  
  44. public void setWeight(int weight) {
  45. this.weight = weight;
  46. }
  47.  
  48. @Override
  49. public int compareTo(Edge o) {
  50. if (o.weight > this.weight) {
  51. return -1;
  52. } else {
  53. return 1;
  54. }
  55. }
  56. }
  57.  
  58. public class Kruskal {
  59.  
  60. public static void main(String[] args) {
  61. //默认以a为根节点的最小生成树
  62. List<Edge> list = new ArrayList<>();
  63. int[][] arr = new int[][]{
  64. {-1, 4, 0, 0, 0, 0, 0, 8, 0},
  65. {0, -1, 8, 0, 0, 0, 0, 11, 0},
  66. {0, 0, -1, 7, 0, 4, 0, 0, 2},
  67. {0, 0, 0, -1, 9, 14, 0, 0, 0},
  68. {0, 0, 0, 0, -1, 10, 0, 0, 0},
  69. {0, 0, 0, 0, 0, -1, 2, 0, 0},
  70. {0, 0, 0, 0, 0, 0, -1, 1, 6},
  71. {0, 0, 0, 0, 0, 0, 0, -1, 7},
  72. {0, 0, 0, 0, 0, 0, 0, 0, -1}
  73. };
  74. for (int i = 0; i < arr.length; i++) {
  75. for (int j = i + 1; j < arr.length; j++) {
  76. if (arr[i][j] > 0) {
  77. list.add(new Edge(i, j, arr[i][j]));
  78. }
  79. }
  80. }
  81. Collections.sort(list);
  82. //数组中每一个节点都只知道他的父节点是什么,-1表示不存在父节点,0位置是根节点
  83. int[] parent = new int[arr.length];
  84. for (int i = 1; i < arr.length; i++) {
  85. parent[i] = -1;
  86. }
  87. int m = 0, n = 0;
  88. for (Edge edge : list) {
  89. //寻找这两个点有没有相同的父节点
  90. m = find(parent, edge.getBegin());
  91. n = find(parent, edge.getEnd());
  92. if (m != n && parent[edge.getEnd()]>0) {
  93. parent[edge.getEnd()] = edge.getBegin();
  94. }
  95. }
  96. System.out.println(Arrays.toString(parent));
  97. }
  98.  
  99. private static int find(int[] parent, int ch) {
  100. while (parent[ch] > 0) {
  101. ch = parent[ch];
  102. }
  103. return ch;
  104. }
  105. }

图的最小生成树(java实现)的更多相关文章

  1. 图的存储,搜索,遍历,广度优先算法和深度优先算法,最小生成树-Java实现

    1)用邻接矩阵方式进行图的存储.如果一个图有n个节点,则可以用n*n的二维数组来存储图中的各个节点关系. 对上面图中各个节点分别编号,ABCDEF分别设置为012345.那么AB AC AD 关系可以 ...

  2. hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)

    还是畅通工程 Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...

  3. 三张图彻底了解Java中字符串的不变性

    转载: 三张图彻底了解Java中字符串的不变性 定义一个字符串 String s = "abcd"; s中保存了string对象的引用.下面的箭头可以理解为"存储他的引用 ...

  4. PowerDesigner(八)-面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)(转)

    面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...

  5. C++编程练习(10)----“图的最小生成树“(Prim算法、Kruskal算法)

    1.Prim 算法 以某顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树. 2.Kruskal 算法 直接寻找最小权值的边来构建最小生成树. 比较: Kruskal 算法主要是针对边来展开,边数 ...

  6. "《算法导论》之‘图’":最小生成树(无向图)

    本文主要参考自<算法>. 加权图是一种为每条边关联一个权值或是成本的图模型.这种图能够自然地表示许多应用.在一幅航空图中,边表示航线,权值则可以表示距离或是费用.在一幅电路图中,边表示导线 ...

  7. 无向带权图的最小生成树算法——Prim及Kruskal算法思路

    边赋以权值的图称为网或带权图,带权图的生成树也是带权的,生成树T各边的权值总和称为该树的权. 最小生成树(MST):权值最小的生成树. 生成树和最小生成树的应用:要连通n个城市需要n-1条边线路.可以 ...

  8. 八、面向对象模型(用例图,序列图,类图,生成Java源代码及Java源代码生成类图)

    面向对象模型 面向对象模型是利用UML(统一建模语言)的图形来描述系统结构的模型,它从不同角度实现系统的工作状态.这些图形有助于用户,管理人员,系统分析人员,开发人员,测试人员和其他人员之间进行信息交 ...

  9. java基础思维导图,让java不再难懂

    java基础思维导图,让java不再难懂 原文链接  https://my.oschina.net/u/3080373/blog/873056 最近看了一些文章的思维导图,发现思维导图真是个强大的工具 ...

随机推荐

  1. 2.3负载均衡:Ribbon

    基于上一篇文章的工程,启动eureka-server 工程:启动service-hi工程,它的端口为8765:将service-hi的配置文件的端口改为8763,并启动,这时你会发现:service- ...

  2. LeetCode 61——旋转链表(JAVA)

    给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = 2 输出: 4-& ...

  3. 5.Linux常用排查命令

    可以使用一下命令查使用内存最多的10个线程     ps aux | sort -k4nr | head -n 10   可以使用一下命令查使用CPU最多的10个线程     ps aux | sor ...

  4. PB各对象常用事件

    1.window中的事件 事件名                  触发的时机 01.Activate            在窗口激活之前触发 02.Clicked             当用户用 ...

  5. command not found 的解决&&解释

    ln -s /opt/platform/calico/calicoctl /usr/local/sbin/calicoctl ln -s /opt/platform/nginx/sbin/nginxl ...

  6. Django模型(model)系统

    Object Relational Mapping(ORM) ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据 ...

  7. C# 使用Emit实现动态AOP框架 (一)

    目  录 C# 使用Emit实现动态AOP框架 (一) C# 使用Emit实现动态AOP框架 (二) C# 使用Emit实现动态AOP框架 (三) C# 使用Emit实现动态AOP框架 进阶篇之异常处 ...

  8. 我是如何将一个加载90s的接口优化到不足2s的

    一.提出问题 由于公司是做医疗级智能可穿戴设备的,所以数据(二进制数据)的存储方面有点特殊,数据没有存储于数据库里面,而是存储于磁盘上.可能有同学质疑,mysql的Blob类型也可以存储二进制数据啊, ...

  9. SparkSQL读取HBase数据

    这里的SparkSQL是指整合了Hive的spark-sql cli(关于SparkSQL和Hive的整合,见文章后面的参考阅读). 本质上就是通过Hive访问HBase表,具体就是通过hive-hb ...

  10. body测试onclick等鼠标事件无效果详解

    DOM事件机制包括五部分: DOM事件级别 DOM事件流 DOM事件模型 事件代理 Event对象常见的方法和属性 但是有时候发现给body标签里设置onclick属性,不起作用,代码如下: 不管单击 ...