普利姆算法

基本介绍

普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。

案例


1)有胜利乡有7个村庄(A, B, C, D, E, F, G) ,现在需要修路把7个村庄连通
2)各个村庄的距离用边线表示(权) ,比如 A – B 距离 5公里
3)问:如何修路保证各个村庄都能连通,并且总的修建公路总里程最短?

最小生成树

这个问题本质上就是最小生成树问题,最小生成树:一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。

思路

代码

import java.util.Arrays;

public class PrimAlgorithm {
  public static void main(String[] args) {
    char[] data = {'A','B','C','D','E','F','G'};
    int [][]weight=new int[][]{  //10000表示不通
            {10000,5,7,10000,10000,10000,2},
            {5,10000,10000,9,10000,10000,3},
            {7,10000,10000,10000,8,10000,10000},
            {10000,9,10000,10000,10000,4,10000},
            {10000,10000,8,10000,10000,5,4},
            {10000,10000,10000,4,5,10000,6},
            {2,3,10000,10000,4,6,10000},};
    int vertex = data.length;
    MGraph graph = new MGraph(vertex);
    MinTree minTree = new MinTree();
    minTree.createGraph(graph,vertex,data,weight);
    minTree.showGraph(graph);
    minTree.prim(graph,0);
  }
}

class MGraph {
  int vertex; //顶点个数
  char[] data;  //存放顶点
  int[][] weight; //邻接矩阵

  public MGraph(int vertex) {
    this.vertex = vertex;
    weight = new int[vertex][vertex];
    data = new char[vertex];
  }
}

class MinTree {

  /**
   * 创建图的邻接矩阵
   * @param graph 图对象
   * @param vertex 图顶点个数
   * @param data 图的顶点的值
   * @param weight 图对应的邻接矩阵
   */
  public void createGraph(MGraph graph,int vertex,char[] data,int[][] weight) {
    int i, j;
    for(i = 0; i < vertex; i++) {
      graph.data[i] = data[i];
      for(j = 0; j < vertex; j++) {
        graph.weight[i][j] = weight[i][j];
      }
    }
  }

  /**
   * 显示图的邻接矩阵
   * @param graph 图对象
   */
  public void showGraph(MGraph graph) {
    for (int[] link : graph.weight) {
      System.out.println("link = " + Arrays.toString(link));
    }
  }

  /**
   * 普利姆算法
   * @param graph 图对象
   * @param v 表示从哪个顶点开始
   */
  public void prim(MGraph graph,int v) {
    int[] visited = new int[graph.vertex];  //0表示未使用,1表示已使用
    visited[v] = 1;
    int index1 = 0;
    int index2 = 0;
    int minWeight = Integer.MAX_VALUE;  //假设最小权值
    for (int i = 1; i < graph.vertex; i++) {
      for (int j = 0; j < graph.vertex; j++) {
        for (int k = 0; k < graph.vertex; k++) {
          if (visited[j] == 1 && visited[k] == 0 && graph.weight[j][k] < minWeight) {
            minWeight = graph.weight[j][k];
            index1 = j;
            index2 = k;
          }
        }
      }
      System.out.println("边为=>" + graph.data[index1] + ">" + graph.data[index2] + ",权值是" + minWeight);
      visited[index2] = 1;
      minWeight = Integer.MAX_VALUE;
    }
  }

}

posted @   翻蹄亮掌一皮鞋  阅读(423)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示