• 最小生成树


    目录

    带权图

    带权图java代码实现

    最小生成树

    Kruskal算法

    ​切分定理

    Kruskal算法的java代码实现

    Prim算法

    Prim算法的java代码实现

     总结


    带权图

     边上的权是附加的额外信息,可以代表不同公路的收费等你需要的信息。

    带权图java代码实现

    1. port java.io.File;
    2. import java.io.IOException;
    3. import java.util.Map;
    4. import java.util.TreeMap;
    5. import java.util.Scanner;
    6. import java.util.TreeSet;
    7. //暂时支持无向带权图
    8. public class WeightedGraph {
    9. private int V;
    10. private int E;
    11. //TreeMap传入的第二个元素是权值类型
    12. // 我们这里用的是Integer,具体用什么可以自行修改
    13. private TreeMap[] adj;
    14. public WeightedGraph(String file){
    15. File file = new File(filename);
    16. try(Scanner scanner = new Scanner(file)){
    17. V = scanner.nextInt();//读取顶点信息
    18. if(V < 0) throw new IllegalArgumentException("V must be non-negative");
    19. adj = new TreeMap[V];
    20. for(int i = 0; i < V; i++){
    21. adj[i] = new TreeMap();
    22. }
    23. E = scanner.nextInt();//读取边的信息
    24. if(E < 0) throw new IllegalArgumentException("E must be non-negative");
    25. for(int i = 0; i < E; i++){
    26. int a = scanner.nextInt();
    27. validateVertex(a);
    28. int b = scanner.nextInt();
    29. validateVertex(b);//判断合法性
    30. int wight = scanner.nextInt();//读取权值
    31. //不要自环边
    32. if(a == b) throw new IllegalArgumentException("Self Loop is Detected!");
    33. //不要平行边
    34. if(adj[a].containsKey(b)) throw new IllegalArgumentException("");
    35. adj[a].put(b, weight);//传入weight
    36. adj[b].put(a, weight);
    37. }
    38. }
    39. catch(IOException e){
    40. e.printStackTrace();
    41. }
    42. }
    43. public void validateVertex(int v) {
    44. if (v < 0 || v >= V) {
    45. throw new IllegalArgumentException("vertex" + "is invalid");
    46. }
    47. }
    48. public int V() {return V;}
    49. public int E() {return E;}
    50. public boolean hasEdge(int v, int w){
    51. validateVertex(v);
    52. validateVertex(w);
    53. return adj[v].containsKey(w);
    54. }
    55. //返回和v相邻的所有顶点
    56. public Iterable adj(int v){
    57. validateVertex(v);
    58. return adj[v].keySet();//返回TreeMap中所有的键
    59. }
    60. //返回权值
    61. public int getWeight(int v, int w){
    62. if(hasEdge(v, w))
    63. return adj[v].get(w);//获得w这个键对应的权值
    64. throw new IllegalArgumentException(String.format("no edge %d - %d", v, w));
    65. }
    66. public int degree(int v){
    67. validateVertex(v);
    68. return adj[v].size();
    69. }
    70. public void removeEdge(int v, int w){
    71. validateVertex(v);
    72. validateVertex(w);
    73. adj[v].remove(w);
    74. adj[w].remove(v);
    75. }
    76. @Override
    77. public Object clone(){
    78. try{
    79. WeightedGraph cloned = (WeightedGraph) super.clone();
    80. cloned.adj = new TreeMap[V];
    81. for(int v = 0; v < V; v++){
    82. cloned.adj[v] = new TreeMap();
    83. for(Map.Entryentry : adj[v].entrySet())
    84. cloned.adj[v].put(entry.getKey(), entry.getValue());
    85. }
    86. return cloned;
    87. }
    88. catch(CloneNotSupportedException e){
    89. e.printStackTrace();
    90. }
    91. return null;
    92. }
    93. @Override
    94. public String toString(){
    95. StringBuilder sb = new StringBuilder();
    96. sb.append(String.format("V = %d, E = %d\n"), V, E);
    97. for(int v = 0; v < V; v++){
    98. sb.append(String.format("%d : ", v));
    99. for(Map.Entryentry : adj[v].entrySet())
    100. sb.append(String.format("(%d : %d)", entry.getKey(), entry.getValue()));
    101. sb.append('\n');
    102. }
    103. return sb.toString();
    104. }
    105. public static void main(String[]args){
    106. WeightedGraph g = new WeightedGraph("g.txt");
    107. System.out.println(g);
    108. }
    109. }

    最小生成树

    Kruskal算法

    同一张图的不同生成树的权值和大小不同,最小生成树就是求权值和最小的生成树。

    在选最短的边的同时要注意不要和已选的边形成环。如下图,我们成功选了六条边连接了七个顶点,形成了最小生成树。

     切分定理

     Kruskal算法的java代码实现

    1. import java.util.ArrayList;
    2. import java.util.Collections;
    3. public class Kruskal {
    4. private WeightedGraph G;
    5. private ArrayList mst;
    6. public Kruskal(WeightedGraph G){
    7. this.G = G;
    8. mst = new ArrayList<>();
    9. CC cc = new CC(G);
    10. if(cc.count() > 1) return;
    11. ArrayList edges = new ArrayList<>();
    12. for(int v = 0; v < G.V(); v ++)
    13. for(int w: G.adj(v))
    14. if(v < w)
    15. edges.add(new WeightedEdge(v, w, G.getWeight(v, w)));
    16. Collections.sort(edges);
    17. UF uf = new UF(G.V());
    18. for(WeightedEdge edge: edges){
    19. int v = edge.getV();
    20. int w = edge.getW();
    21. if(!uf.isConnected(v, w)){
    22. mst.add(edge);
    23. uf.unionElements(v, w);
    24. }
    25. }
    26. }
    27. public ArrayList result(){
    28. return mst;
    29. }
    30. public static void main(String[] args){
    31. WeightedGraph g = new WeightedGraph("g.txt");
    32. Kruskal kruskal = new Kruskal(g);
    33. System.out.println(kruskal.result());
    34. }
    35. }

     

    Prim算法

    Prim算法的java代码实现

    1. import java.util.ArrayList;
    2. import java.util.Queue;
    3. import java.util.PriorityQueue;
    4. public class Prim {
    5. private WeightedGraph G;
    6. private ArrayList mst;
    7. public Prim(WeightedGraph G){
    8. this.G = G;
    9. mst = new ArrayList<>();
    10. CC cc = new CC(G);
    11. if(cc.count() > 1) return;
    12. boolean visited[] = new boolean[G.V()];
    13. visited[0] = true;
    14. Queue pq = new PriorityQueue();
    15. for(int w: G.adj(0))
    16. pq.add(new WeightedEdge(0, w, G.getWeight(0, w)));
    17. while(!pq.isEmpty()){
    18. WeightedEdge minEdge = (WeightedEdge) pq.remove();
    19. if(visited[minEdge.getV()] && visited[minEdge.getW()])
    20. continue;
    21. mst.add(minEdge);
    22. int newv = visited[minEdge.getV()] ? minEdge.getW() : minEdge.getV();
    23. visited[newv] = true;
    24. for(int w: G.adj(newv))
    25. if(!visited[w])
    26. pq.add(new WeightedEdge(newv, w, G.getWeight(newv, w)));
    27. }
    28. }
    29. public ArrayList result(){
    30. return mst;
    31. }
    32. public static void main(String[] args){
    33. WeightedGraph g = new WeightedGraph("g.txt");
    34. Prim prim = new Prim(g);
    35. System.out.println(prim.result());
    36. }
    37. }

     总结

  • 相关阅读:
    冗余是什么
    优雅地记录http请求和响应的数据
    C#/.NET/.NET Core优秀项目和框架2024年2月简报
    智能生活 App 垂直品类- IPC SDK 架构及快速集成配置(安卓版)
    #微信小程序(按键控制)
    MQ发布确认
    ElasticSearch入门
    记一次封装接口返回值问题
    【FPGA教程案例39】通信案例9——基于FPGA的交织-解交织数据传输
    【JVM基础】虚拟机栈
  • 原文地址:https://blog.csdn.net/xiaoliii0401/article/details/134417444