最小生成树——Prim(普利姆)算法

【0】README

0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解Prim算法的idea 并用 源代码加以实现;
0.2)最小生成树的基础知识,参见 http://blog.csdn.net/pacosonswjtu/article/details/49947085


【1】Prim算法相关

1.1)计算最小生成树的一种方法是使其连续地一步一步长成。在每一步, 都要吧一个节点当做根并往上加边,这样也就把相关联的顶点加到增长中的树上;
1.2)在算法中的任一时刻, 我们都可以看到一个已经添加到树上的顶点集, 而其余顶点尚未加到这颗树中。此时, 算法在每一阶段都可以通过选择边(u, v),使得(u, v)的值是所有u 在树上但v不在树上的边的值中的最小者, 而找出一个新的顶点并吧它添加到这颗树中;
1.3)具体步骤概括为:

  • step1)给定一个顶点为根节点;
  • step2)每一步加一条边和一个顶点; (这也迎合了 顶点个数-边个数=1 );

1.4)看个荔枝:

对上图的分析(Analysis):
A1)可以看到, 其实Prim算法基本上和求最短路径的 Dijkstra算法一样, 因此和前面一样,我们对每一个顶点保留值 Dv和Pv 以及一个指标,指示该顶点是已知的还是未知的。这里,Dv是连接v 到已知顶点的最短边的权, 而 Pv则是导致Dv改变的最后的顶点。
A2)算法的其余部分一样, 唯一不同的是: 由于Dv的定义不同, 因此它的更新法则不一样。事实上,Prim算法的更新法则比 Dijkstra算法简单:在每一个顶点v被选取后, 对于每一个与 v 邻接的未知的w, Dw=min(Dw, Cw,v);
这里写图片描述
对上图的分析(Analysis):
A1)该算法整个的实现实际上和 Dijkstra算法的实现是一样的, 对于 Dijkstra算法分析所做的每一件事都可以用到这里。 不过要注意, Prim算法是在无向图上运行的, 因此当编写代码的时候要记住要吧每一条变都要放到两个邻接表中。
A2)不用堆时的运行时间为O(|V|^2), 它对于稠密图来说是最优的; 使用二叉堆的运行时间为 O(|E|log|V|), 它对于稀疏图是一个好的界限;


【2】source code + printing results(将我的代码打印结果 同 上图中的手动模拟的prim算法的结果进行比较,你会发现, 它们的结果完全相同,这也证实了我的代码的可行性)

2.1)download source code: https://github.com/pacosonTang/dataStructure-algorithmAnalysis/tree/master/chapter9/p237_prim
2.2)source code at a glance(for complete code , please click the given link above):

#include "prim.h"//allocate the memory for initializing unweighted table
WeightedTable *initWeightedTable(int size)
{   WeightedTable* table;int i;table = (WeightedTable*)malloc(sizeof(WeightedTable) * size);if(!table){Error("out of space ,from func initWeightedTable");return NULL;}for(i = 0; i < size; i++){table[i] = makeEmptyWeightedTable();        if(!table[i])return NULL;}return table;
} // allocate the memory for every element in unweighted table  
WeightedTable makeEmptyWeightedTable()
{WeightedTable element;element = (WeightedTable)malloc(sizeof(struct WeightedTable));if(!element){Error("out of space ,from func makeEmptyWeightedTable");return NULL;}   element->known = 0; // 1 refers to accessed , also 0 refers to not accessedelement->distance = MaxInt;element->path = -1; // index starts from 0 and -1 means the startup vertex unreaches other vertexsreturn element;
}// allocate the memory for storing index of  vertex in heap and let every element -1
int *makeEmptyArray(int size)
{int *array;int i;array = (int*)malloc(size * sizeof(int));if(!array){Error("out of space ,from func makeEmptyArray");return NULL;}       for(i=0; i<size; i++)array[i] = -1;return array;
}//computing the unweighted shortest path between the vertex under initIndex and other vertexs
void prim(AdjTable* adj, int size, int startVertex, BinaryHeap bh)
{       int adjVertex;  int tempDistance;WeightedTable* table;int vertex;     AdjTable temp;  Distance tempDisStruct;int *indexOfVertexInHeap;int indexOfHeap;table = initWeightedTable(size);        tempDisStruct = makeEmptyDistance();indexOfVertexInHeap = makeEmptyArray(size);tempDisStruct->distance = table[startVertex-1]->distance;tempDisStruct->vertexIndex = startVertex-1;insert(tempDisStruct, bh, indexOfVertexInHeap); // insert the (startVertex-1) into the binary heap  table[startVertex-1]->distance = 0;// update the distance table[startVertex-1]->path = 0;// update the path of starting vertexwhile(!isEmpty(bh)){       vertex = deleteMin(bh, indexOfVertexInHeap).vertexIndex; // return the minimal element in binary heap//printBinaryHeap(bh);table[vertex]->known = 1; // update the vertex as accessed, also let responding known be 1temp = adj[vertex]->next;while(temp){adjVertex = temp->index; if(table[adjVertex]->known == 1) // judge whether table[adjVertex]->known is 1 or not{temp = temp->next;continue;}//tempDistance = table[vertex]->distance + temp->weight; // update the distancetempDistance = temp->weight;if(tempDistance < table[adjVertex]->distance){table[adjVertex]->distance = tempDistance;table[adjVertex]->path = vertex; //update the path of adjVertex, also responding path evaluated as vertex                           // key, we should judge whether adjVertex was added into the binary heap                //if true , obviously the element has been added into the binary heap(so we can't add the element into heap once again)if(indexOfVertexInHeap[adjVertex] != -1) {indexOfHeap = indexOfVertexInHeap[adjVertex];bh->elements[indexOfHeap]->distance = tempDistance; // update the distance of corresponding vertex in binary heap}else // if not ture{tempDisStruct->distance = table[adjVertex]->distance;tempDisStruct->vertexIndex = adjVertex;insert(tempDisStruct, bh, indexOfVertexInHeap); // insert the adjVertex into the binary heap}}            temp = temp->next;      }       printPrim(table, size, startVertex);        printBinaryHeap(bh);printf("\n");}       printf("\n");
} //print unweighted table
void printPrim(WeightedTable* table, int size, int startVertex)
{int i;  char *str[4] = {"vertex","known","distance","path"};printf("\n\t === storage table related to Prim alg as follows: === ");  printf("\n\t %6s%6s%9s%5s", str[0], str[1], str[2], str[3]);    for(i=0; i<size; i++){       if(i != startVertex-1 && table[i]->path!=-1) printf("\n\t %-3d   %3d   %5d      v%-3d  ", i+1, table[i]->known, table[i]->distance, table[i]->path+1);else if(table[i]->path == -1)printf("\n\t %-3d   %3d   %5d      %-3d  ", i+1, table[i]->known, table[i]->distance, table[i]->path);elseprintf("\n\t *%-3d  %3d   %5d      %-3d  ", i+1, table[i]->known, table[i]->distance, 0);}    
}int main()
{ AdjTable* adj;  BinaryHeap bh;int size = 7;int capacity;int i;int j;  int startVertex;int adjTable[7][7] = {{0, 2, 4, 1, 0, 0, 0},{2, 0, 0, 3, 10, 0, 0},{4, 0, 0, 2, 0, 5, 0},{1, 3, 2, 0, 7, 8, 4},{0, 10, 0, 7, 0, 0, 6},{0, 0, 5, 8, 0, 0, 1},{0, 0, 0, 4, 6, 1, 0},};printf("\n\n\t ====== test for Prim alg finding weighted shortest path from adjoining table ======\n");adj = initAdjTable(size);       printf("\n\n\t ====== the initial weighted adjoining table is as follows:======\n");for(i = 0; i < size; i++)for(j = 0; j < size; j++)   if(adjTable[i][j])          insertAdj(adj, j, i, adjTable[i][j]); // insertAdj the adjoining table overprintAdjTable(adj, size);   capacity = 7;bh = initBinaryHeap(capacity+1);//conducting prim alg to find minimum spanning tree(MST)startVertex = 1; // you should know our index for storing vertex starts from 0prim(adj, size, startVertex, bh);   return 0;
} 

2.3)printing results:

这里写图片描述
这里写图片描述
这里写图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/331873.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql grant usage on_grant 权限 on 数据库对象 to 用户

grant 权限 on 数据库对象 to 用户一、grant 普通数据用户&#xff0c;查询、插入、更新、删除 数据库中所有表数据的权利。grant select on testdb.* to common_user’%’grant insert on testdb.* to common_user’%’grant update on testdb.* to common_user’%’grant del…

openjdk8 项目结构_OpenJDK织机和结构化并发

openjdk8 项目结构Project Loom是Hotspot Group赞助的项目之一&#xff0c;旨在向JAVA世界提供高吞吐量和轻量级的并发模型。 在撰写本文时&#xff0c;Loom项目仍在积极开发中&#xff0c;其API可能会更改。 为什么要织机&#xff1f; 每个新项目可能会出现的第一个问题是为什…

mysql连库串_数据库连接串整理 - osc_ac5z111b的个人空间 - OSCHINA - 中文开源技术交流社区...

常用JDBC驱动与连接字符串MySQLdriver&#xff1a;com.mysql.jdbc.Driverurl&#xff1a;jdbc:mysql://localhost:3306/mydbMySQL url格式&#xff1a;jdbc:mysql://[host:port]/[database][?参数名1][参数值1][&参数名2][参数值2]…参数名称参数说明缺省值最低版本要求us…

最小生成树——Kruskal(克鲁斯卡尔)算法

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 Kruskal&#xff08;克鲁斯卡尔&#xff09;算法 的idea 并用 源代码加以实现&#xff1b; 0.2&#xff09;最小生成树的基础知识&#xff0c;参见 http://blo…

java 正则表达式 开头_如何在Java中修复表达式的非法开头

java 正则表达式 开头您是否遇到过这个令人难以置信的错误&#xff0c;想知道如何解决它&#xff1f; 让我们仔细阅读一下&#xff0c;研究如何解决表达式Java非法开头错误。 这是一个动态错误&#xff0c;这意味着编译器会发现某些不符合Java编程规则或语法的内容。 初学者大…

php mysql数据备份命令_MySQL数据备份与恢复的相关操作命令

将mysql安装目录设置到系统环境变量中, 方便在命令行终端直接执行.linux下mysql安装后, root默认密码为空, 可直接执行mysql 登录将mysql安装目录设置到系统环境变量中, 方便在命令行终端直接执行.linux下mysql安装后, root默认密码为空, 可直接执行mysql 登录.正常登录命令mys…

DFS——深度优先搜索基础

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 review DFS——深度优先搜索 的基础知识&#xff1b; 【1】深度优先搜索的应用 1.1&#xff09;深度优先搜索算法描述&#xff08;转自天勤计算机考研高分笔记——数…

rest post put_REST / HTTP方法:POST与PUT与PATCH

rest post put每个HTTP请求都包含一个方法 &#xff08;有时称为verb &#xff09;&#xff0c;该方法指示对标识的资源执行的操作。 在构建RESTful Web服务时&#xff0c;HTTP方法POST通常用于创建资源&#xff0c;而PUT用于资源更新。 尽管在大多数情况下这很好&#xff0c;…

回归模型的score得分为负_深度研究:回归模型评价指标R2_score

回归模型的性能的评价指标主要有&#xff1a;RMSE(平方根误差)、MAE(平均绝对误差)、MSE(平均平方误差)、R2_score。但是当量纲不同时&#xff0c;RMSE、MAE、MSE难以衡量模型效果好坏。这就需要用到R2_score&#xff0c;实际使用时&#xff0c;会遇到许多问题&#xff0c;今天…

DFS应用——遍历无向图

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 如何对无向图进行深度优先搜索 的idea 并用源代码加以实现&#xff1b; 0.2&#xff09; 本文还引入了 背向边&#xff08;定义见下文描述&#xff09;&#x…

高效的磁力搜索引擎 -_高效的企业测试-结论(6/6)

高效的磁力搜索引擎 -该系列的最后一部分将涵盖其他端到端测试&#xff0c;生产中的测试以及各部分的结论。 进一步的端到端测试和生产中的测试 除了仅验证单个被测应用程序并模拟外部问题的系统测试之外&#xff0c;我们的管道还必须包括完整的端对端测试&#xff0c;以验证…

linux安装mysql phpmyadmin_ubuntu mysql远程连接+phpmyadmin安装

一、如何让ubuntu上的mysql允许远程连接进入MySQL&#xff0c;执行如下命令:use mysql;GRANT ALL PRIVILEGES ON *.* TO username% IDENTIFIED BY password WITH GRANT OPTION;flush privileges; //刷新select host,user from user; //查看是否成功退出mysql&#xff1b;打开su…

DFS应用——找出无向图的割点

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 “DFS应用于找割点” 的idea 并用源代码加以实现&#xff1b; 0.2&#xff09; 必须要事先 做个specification的是&#xff1a;对于给定图的除开起始vertex的那…

spock测试_将Spock 1.3测试迁移到Spock 2.0

spock测试了解Spock 2.0 M1&#xff08;基于JUnit 5&#xff09;的期望&#xff0c;如何在Gradle和Maven中迁移到它以及为什么报告发现的问题很重要&#xff1a;&#xff09;。 重要说明 。 我绝对不建议您永久将您的现实项目迁移到Spock 2.0 M1&#xff01; 这是2.x的第一个&…

mysql与jmeter环境变量配置_Java开发技术大杂烩(一)之Redis、Jmeter、MySQL的那些事...

前言毕业答辩告一段落&#xff0c;接下来好好努力工作。Redis遇到的一些问题DENIED Redis is running in protected mode because protected mode is enabled, no bind address was specified, no authentication password is requested to clients. In this mode connections …

DFS应用——寻找欧拉回路

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 “DFS应用——寻找欧拉回路” 的idea 并用源代码加以实现 &#xff08;源代码&#xff0c;我还没有找到一种有效的数据结构和DFS进行结合&#xff0c;往后会po出…

wiremock 使用_使用WireMock进行更好的集成测试

wiremock 使用无论您是遵循传统的测试金字塔还是采用诸如“ 测试蜂窝”这样的较新方法&#xff0c;都应该在开发过程中的某个时候开始编写集成测试。 您可以编写多种类型的集成测试。 从持久性测试开始&#xff0c;您可以检查组件之间的交互&#xff0c;也可以模拟调用外部服务…

mysql备份七牛云存储_定时备份 Mysql并上传到七牛的方法

多数应用场景下&#xff0c;我们需要对重要数据进行备份、并放置到一个安全的地方&#xff0c;以备不时之需。常见的 MySQL 数据备份方式有&#xff0c;直接打包复制对应的数据库或表文件(物理备份)、mysqldump 全量逻辑备份、xtrabackup 增量逻辑备份等。常见的数据存储方式有…

jetty java_Jetty,Java和OAuth入门

jetty java使用Okta的身份管理平台轻松部署您的应用程序 使用Okta的API在几分钟之内即可对任何应用程序中的用户进行身份验证&#xff0c;管理和保护。 今天尝试Okta。 Jetty是一个小型&#xff0c;高度可扩展的基于Java的Web服务器和servlet引擎。 它支持HTTP / 2&#xff0c…

DFS应用——查找强分支

【0】README 0.1&#xff09; 本文总结于 数据结构与算法分析&#xff0c; 源代码均为原创&#xff0c; 旨在 理解 “DFS应用——查找强分支” 的idea 并用源代码加以实现 &#xff1b; 【1】查找强分支 1.1&#xff09;如何检测一个图是否是强连通的&#xff1a; 通过执行两…