(数据结构)普利姆算法(Prim)实现

这篇具有很好参考价值的文章主要介绍了(数据结构)普利姆算法(Prim)实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

普利姆(Prim算法)

假设要在n个城市之间建立通信联络网,每两个城市之间建立线路都需要花费不同大小的经费,则连通n个城市只需要n-1个条线路,最小生成树解决的问题就是:如何在最节省经费的前提下建立这个通信网

也可以理解为:n个城市之间最多可以建立n(n-1)/2条线路,我们要从这里挑出n-1条线路

算法思路

下面就是普里姆算法(Prim)的大致思路:

该算法又称加点法,顾名思义就是一步一步地将顶点加入到集合U中,所以,我们需要维护一个tag数组,其中 tag[i]=true 就表示第i个顶点已被加入到集合U中

bool tag[maxn];   //标记,tag[i]=1表示顶点i在集合U中
1

同时,我们还要维护一个辅助数组closedge,用于表示 没有加入到集合U的顶点已经加入到集合U的顶点 的最小权值
closedge[i] 中的 i 就是指还没有加入集合U的那个顶点,closedge[i].adjvex指的就是顶点i连接的那个已经在集合U中的顶点

struct{
	int adjvex;  //最小边在U中的那个顶点
	int lowcost;  //最小边上的权值
}closedge[maxn];
1234

下面废话不多说,直接上图

有这样的一个无向连通图,我们接下来需要求的是这个图的最小生成树
prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

  1. 我们从顶点A开始,先把顶点A加入到集合U中(这里就标记为绿色了)
    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

  2. 然后扫描与顶点A直接相连的顶点,初始化closedge
    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

  3. 然后扫描closedge,发现C的lowcost最小,所以把C加入集合U中,产生一条边A -- C
    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论
    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

  4. 扫描与C直接相连的顶点A B D E F
    (1) A已加入集合U,忽略
    (2) B与C相连的边的权值为5,比原来记录的6还要小,所以更新顶点B的adjvex为C,lowcost为5
    (3) D与C相连的边的权值为5,并不比原来的小,可以跳过
    (4) E和F在closedge中没有记录,直接加入即可

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    5.现在F的lowcost最小,把F加入到集合U,并更新closedge

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    6.目前D的lowcost最小,执行一样的操作

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    7.现在B的lowcost最小

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    8.剩下最后一个顶点B

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    所以该图的最小生成树如下图所示:

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论

    留下的5条边刚好是表格中的这5条边

    prim算法实现:“加点法”,数据结构秃头之路,算法,数据结构,图论文章来源地址https://www.toymoban.com/news/detail-769757.html

实现

c++邻接表存储法+再打印
c++
 #include <iostream>
 using namespace std;
 typedef long long ll;
 # define maxn 1024    //最大顶点数量
 int matrix[maxn][maxn];   //邻接矩阵
 bool tag[maxn];   //标记,tag[i]=1表示顶点i在集合U中
 int n, m;  //n:顶点个数(其中顶点标号从1到n)  m:边的个数
 struct {
 	int adjvex;  //最小边在U中的那个顶点
 	int lowcost;  //最小边上的权值
 }closedge[maxn];
 
 /*
 增加一条连接n1顶点和n2顶点的边,权值为k
 */
 void link(int n1, int n2, int k) {
 	matrix[n1][n2] = k;
 	matrix[n2][n1] = k;
 }
 
 /*
 初始化
 */
void init() {
 	//初始化邻接矩阵
 	for (int i = 0; i < maxn; ++i) {
 		for (int j = 0; j < maxn; ++j) {
 			matrix[i][j] = -1;
 		}
 	}
	memset(tag, 0, sizeof(maxn));
 	n = 6;   //一共有6个顶点
 	m = 10;   //10条边
  
  //link(0, 3, 7);
 	//link(0, 5, 3);
 	//link(0, 2, 8);
 	//link(0, 1, 5);
 	//link(1, 2, 4);
 	//link(2, 3, 5);
 	//link(2, 5, 9);
 	//link(3, 5, 6);
 	//link(3, 4, 5);
 	//link(4, 5, 1);
 	//下面m行都是在建图
	link(1, 2, 6);
 	link(1, 3, 1);
 	link(1, 4, 5);
 	link(2, 3, 5);
 	link(3, 4, 5);
 	link(2, 5, 3);
 	link(3, 5, 6);
 	link(3, 6, 4);
 	link(4, 6, 2);
 	link(5, 6, 6);
 	tag[1] = 1;   //从该顶点出发(把该顶点加入集合U)
 	//对没有加入集合U中的顶点,都初始化closedge
 	for (int i = 2; i <= n; ++i) { 		
 	  closedge[i].adjvex = 1;
 		closedge[i].lowcost = matrix[1][i];
 	}
 };
  /*
 Prim算法开始
 */
 /
 void prim() {
 	int T = n - 1;
 	//循环执行n-1次
 	while (T--) {
 		//首先寻找【不在U集合中】并且【closedge中权值最小】的边
 		int mi = 0x3f3f3f3f;   //记录当前最小的权值
 		int k = 0;   //最小权值时候的顶点
 		for (int i = 1; i <= n; ++i) {
 			if (!tag[i]/*保证不在集合U中*/ && closedge[i].lowcost != -1/*保证边存在*/ && closedge[i].lowcost < mi/*保证权值最小*/) {
 				mi = closedge[i].lowcost;
 				k = i;
 			}
 		}
 		cout << k << " --- " << closedge[k].adjvex << endl;  //找到一条边
 		tag[k] = 1;  //标记
		//更新closedge
 		for (int i = 1; i <= n; ++i) {
 			if (closedge[i].lowcost == -1/*原来的边不存在*/ || (matrix[k][i] != -1 && matrix[k][i] < closedge[i].lowcost)/*保证k--i的边存在并且比原来记录的要小*/) {
 				closedge[i].adjvex = k;
 				closedge[i].lowcost = matrix[k][i];
 			}
 		}
 
 	}
 }
/
  int main() {
 	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
 	init();   //初始化
 	prim();
 	return 0;
 }
 

java直接从邻接矩阵打印
``java
 public class primAlgorithm {
 	public static void main(String[] args) {
 		//测试图是否创建成功
 		char[] data = new char[] {'A','B','C','D','E','F','G'};
 		int verxs = data.length;
 		int[][] weight = new int[][] {
			{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},
	};
 		//创建Mgraph对象
 		Mgrap mgraph = new Mgrap(verxs);
 		//创建一个MinTree对象
 		Mintree minTree = new Mintree();
 		minTree.creatGraph(mgraph, verxs, data, weight);
 		//输出
 		minTree.showGraph(mgraph);
     //测试普利姆
 		minTree.prim(mgraph, 0);
 	}
 }
 


 //创建最小生成树
 
 class Mintree{
 	/**
 	 * 
 	 * @param greap 图对象
 	 * @param verxs 图顶点个数
 	 * @param data  图顶点值
 	 * @param weight 邻接矩阵
 	 */
 	public void creatGraph(Mgrap graph,int verxs,char data[],int[][] weight ) {
 		for (int i = 0; i < verxs; i++) {
 			graph.data[i] = data[i];
 			for(int j =0; j < verxs; j++) {
 				graph.weight[i][j] = weight[i][j];
 		}
 		}
 	}
 	
 	//显示图的邻接矩阵
 	public void showGraph(Mgrap graph) {
 		for(int[] link: graph.weight) {
 			System.out.println(Arrays.toString(link));
 		}
 	}
 	
 	//编写Prim,生成最小生成树
 	/**
 	 * 
 	 * @param graph 图
 	 * @param v    表示从图的第几个顶点开始> 	 */
 	public void prim(Mgrap graph,int v) {
 		//标记tag  默认为0 其他语言不一定会初始化为0
 		int tag[] = new int[graph.verx];
 		//
 		tag[v] = 1;
 		int h1 =-1;
		int h2 =-1;
 		int minheright =100000;
 		for(int k =1;k < graph.verx; k++) {//寻找n-1次
 			//选择不在集合中 且存在的最小边
 			for(int i = 0;i<graph.verx; i++) {
 				for(int j = 0; j<graph.verx; j++) {//遍历矩阵
 					if(tag[i]==1 && tag[j] == 0 && graph.weight[i][j] < minheright) {
                         //如果当前顶点已经遍历 ,隔壁顶点没有遍历, 选出其中最小的那条
						minheright = graph.weight[i][j];
 						h1 = i;
 						h2 = j;
 					}
 				}	
 			}
 			//打印
 			System.out.println("边<"+graph.data[h1] + "," + graph.data[h2] + "> 权值:" + minheright);
 			tag[h2] = 1;
 			minheright = 10000;
 		}
 		
 	}
 }
 class Mgrap{
 	int verx;//图的节点个数
 	char[] data;//存放节点数据
 	int[][] weight;//存放边
 	public Mgrap(int verxs) {
 		this.verx =verxs;
		data = new char[verxs];
 		weight = new int[verxs][verxs];
  }
}

到了这里,关于(数据结构)普利姆算法(Prim)实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构作业—第十三周---- Prim算法 Kruskal算法 Dijkstra算法

    (只看点,不看边,适合边较多的图,即 稠密图 )       是一种按权值的递增次序选择合适的边来构造最小生成树的方法;( 稀疏图 ) 适合带权有向图和带权无向图求单源最短路径; 不适合含负取值的图,求最短路径; 1 . 单选题 简单 7分 对于有n个顶点的带权连通图

    2024年02月15日
    浏览(47)
  • C++数据结构——习题6-5 最小生成树(Prim算法)

    省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。已知村庄数N和可建道路数M,设初始状态下任意村庄之间没有路,请编写程序,根据输入的两村庄间修建道路的费用情况,计算这些村庄

    2024年02月09日
    浏览(81)
  • 大话数据结构-普里姆算法(Prim)和克鲁斯卡尔算法(Kruskal)

       构造连通网的最小代价生成树称为最小生成树,即Minimum Cost Spanning Tree ,最小生成树通常是基于无向网/有向网构造的。   找连通网的最小生成树,经典的有两种算法,普里姆算法和克鲁斯卡尔算法。   普里姆算法,即Prim算法,大致实现过程如下:   (1) 新建数组

    2024年02月05日
    浏览(45)
  • 【数据结构与算法】最小生成树之普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法

      🌱博客主页:大寄一场. 🌱系列专栏:数据结构与算法 😘博客制作不易欢迎各位👍点赞+⭐收藏+➕关注 目录 前言 一、最小生成树的概念 二、最小生成树的求解方法 三、练习题 四、最小生成树在实际应用中的例子 最近非科班的同学学到了最小生成树并询问我,于是想趁

    2024年02月07日
    浏览(42)
  • prim和kruskal算法的正确性证明(贪心、最优子结构)

    贪心选择: 不失一般性,令起始节点为a,与a相连且度最小的另一节点为b,该边记作y,现证明y包括在某最优解中。令G为一颗最小生成树, 若其中包括y,算法正确性得证成立;若不包括y,则将y加入到G中,此时形成环,不考虑环以外节点,删除与a相邻另一条边c,删除后得

    2024年02月01日
    浏览(40)
  • 最小生成树——prim算法实现

    N个城市之间需要铺设一张交通网,使任意两个城市间都有交通路线直达,现已知各个城市之间铺设道路的经济成本,问该如何求算铺网的最低经济成本?为求算最低经济成本,可以假设N个城市就是连通网G的N个顶点,而求算最低成本问题可以转化为在N个城市间找到N-1条边,

    2024年02月08日
    浏览(38)
  • Prim算法实现最小生成树

    例如:要在n个城市之间铺设光缆,主要目标是要使这n个城市的任意两个之间都可以通信,但铺设光缆的费用很高,且各个城市之间铺设光缆的费用不同,因此另一个目标是要使铺设光缆的总费用最低。这就需要找到带权的最小生成树。 将图中所有顶点分为两类:树顶点(已

    2024年02月11日
    浏览(43)
  • 网络算法-python实现prim(基于堆)

    基本思想: 1.从任意顶点开始; 2.逐步扩展边界; 3.每次扩展,选择当前边界边中 最小权重者加入T; 4.直至T中包含的顶点覆盖原图。 伪代码: 割: 图G(V,E)的一个割(cut)是V的一个划分,该划分将集合V分为两个非空的集合。 Empty-Cut引理: 图G不连通,当且仅当存在cut(A, B)没有

    2023年04月09日
    浏览(32)
  • C语言实现Prim算法 —构建最小生成树

    目录 介绍Prim算法前的相关概念 一、Prim算法的思想 二.1、利用图形详细解释Prim算法的思想 Prim算法思想介绍 ​ 二.2利用图形又又解释Prim算法的思想  三、用图示结合代码中重要量进行说明 四、代码实现(用c语言) 带权图 :边赋以权值的图称为网或带权图,带权图的生成树

    2024年02月08日
    浏览(41)
  • 使用邻接矩阵实现最小生成树Prim算法 题目编号:1135

    用邻接矩阵存储无向图,实现最小生成树Prim算法,图中边的权值为整型,顶点个数少于10个。 部分代码提示: #include using namespace std; const int MaxSize = 10; const int INF = 32767; class MGraph { public: MGraph(char a[], int n, int e); private: char vertex[MaxSize]; int arc[MaxSize][MaxSize]; int vertexNum, arcNum; }

    2024年02月06日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包