普里姆算法

合集下载

Prime算法

Prime算法
2.假设存在 Gmin使得cost(Gmin) < cost(G0) 则在 Gmin中存在 <u,v> 不属于G0
3.将<u,v>加入 G0中可得一个环,且 <u,v> 不是该环的最长边(这是因为 <u,v> ∈ Gmin)
4.这与prime每次生成最短边矛盾
5.故假设不成立,命题得证.
5. 时间复杂度
Edge* Fun(int **graph,int length){
//length个点,(length-1)条边
int* V=(int*)calloc(length,sizeof(int));
Edge* E=(Edge*)malloc((length-1)*sizeof(Edge));
//先设起始点,置1说明入队列
(3)找到AB,加入队列V=[A,D,F,B];E=[AD,DF,AB]
……
(5)找到EG,加入队列V=[A,D,F,B,E,C,G];E=[AD,DF,AB,BE,EC,EG]
//边
struct Edge{
int start;
int end;
int length;
};
//需要传入图邻接矩阵graph,点的个数length
Prime
1. 概述
普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小。该算法于1930年由捷克数学家沃伊捷赫·亚尔尼克(英语:Vojtěch Jarník)发现;并在1957年由美国计算机科学家罗伯特·普里姆(英语:Robert C. Prim)独立发现;1959年,艾兹格·迪科斯彻再次发现了该算法。因此,在某些场合,普里姆算法又被称为DJP算法、亚尔尼克算法或普里姆-亚尔尼克算法。

普里姆算法

普里姆算法

普里姆算法
普里姆算法(Prim's Algorithm)是用于求加权连通图的最小生成树的一种算法。

原理:从某个初始顶点开始,依次把它和它的最近邻居连起来,直到所有的顶点都连接起来。

每次选择最近的可连接的顶点加入到已有的最小生成树中,当所有的顶点都被收进集合中时,算法结束。

步骤:
1. 从一个顶点出发,将它加入最小生成树中;
2. 遍历未加入最小生成树中的顶点,找出与已加入最小生成树中的顶点相连接的边中权值最小的顶点,将其加入到最小生成树中;
3. 重复步骤2,直到所有顶点加入到最小生成树中,算法结束。

Prim算法

Prim算法

Prim算法Prim 算法普⾥姆算法介绍普⾥姆 (Prim) 算法,是⽤来求加权连通图的最⼩⽣成树的算法。

基本思想对于图 G ⽽⾔,V 是所有顶点的集合;现在,设置两个新的集合 U 和 T,其中 U ⽤于存放 G 的最⼩⽣成树中的顶点,T 存放 G 的最⼩⽣成树中的边。

从所有 uЄU,vЄ(V-U) (V-U 表⽰出去 U 的所有顶点)的边中选取权值最⼩的边 (u, v),将顶点 v 加⼊集合 U 中,将边(u, v) 加⼊集合 T 中,如此不断重复,直到U=V 为⽌,最⼩⽣成树构造完毕,这时集合 T 中包含了最⼩⽣成树中的所有边。

普⾥姆算法图解以上图 G4 为例,来对普⾥姆进⾏演⽰ (从第⼀个顶点 A 开始通过普⾥姆算法⽣成最⼩⽣成树)。

初始状态:V 是所有顶点的集合,即 V={A,B,C,D,E,F,G};U 和 T 都是空!第 1 步:将顶点 A 加⼊到 U 中。

此时,U={A}。

第 2 步:将顶点 B 加⼊到 U 中。

上⼀步操作之后,U={A}, V-U={B,C,D,E,F,G};因此,边 (A,B) 的权值最⼩。

将顶点 B 添加到 U 中;此时,U={A,B}。

第 3 步:将顶点 F 加⼊到 U 中。

上⼀步操作之后,U={A,B}, V-U={C,D,E,F,G};因此,边 (B,F) 的权值最⼩。

将顶点 F 添加到 U 中;此时,U={A,B,F}。

第 4 步:将顶点 E 加⼊到 U 中。

上⼀步操作之后,U={A,B,F}, V-U={C,D,E,G};因此,边 (F,E) 的权值最⼩。

将顶点 E 添加到 U 中;此时,U={A,B,F,E}。

第 5 步:将顶点 D 加⼊到 U 中。

上⼀步操作之后,U={A,B,F,E}, V-U={C,D,G};因此,边 (E,D) 的权值最⼩。

将顶点 D 添加到 U 中;此时,U={A,B,F,E,D}。

第 6 步:将顶点 C 加⼊到 U 中。

PRIM算法求最小生成树

PRIM算法求最小生成树

xx学院《数据结构与算法》课程设计报告书课程设计题目 PRIM算法求最小生成树院系名称计算机科学与技术系专业(班级)姓名(学号)指导教师完成时间一、问题分析和任务定义在该部分中主要包括两个方面:问题分析和任务定义;1 问题分析本次课程设计是通过PRIM(普里姆)算法,实现通过任意给定网和起点,将该网所对应的所有生成树求解出来。

在实现该本设计功能之前,必须弄清以下三个问题:1.1 关于图、网的一些基本概念1.1.1 图图G由两个集合V和E组成,记为G=(V,E),其中V是顶点的有穷非空集合,E是V中顶点偶对的有穷集,这些顶点偶对称为边。

通常,V(G)和E(G)分别表示图G的顶点集合和边集合。

E(G)也可以为空集。

则图G只有顶点而没有边。

1.1.2 无向图对于一个图G,若边集E(G)为无向边的集合,则称该图为无向图。

1.1.3 子图设有两个图G=(V,E)G’=(V’,),若V’是V的子集,即V’⊆V ,且E’是E的子集,即E’⊆E,称G’是G的子图。

1.1.4 连通图若图G中任意两个顶点都连通,则称G为连通图。

1.1.5 权和网在一个图中,每条边可以标上具有某种含义的数值,该数值称为该边的权。

把边上带权的图称为网。

如图1所示。

1.2 理解生成树和最小生成树之间的区别和联系1.2.1 生成树在一个连通图G中,如果取它的全部顶点和一部分边构成一个子图G’,即:V(G’)= V(G)和E(G’)⊆E(G),若边集E(G’)中的边既将图中的所有顶点连通又不形成回路,则称子图G’是原图G的一棵生成树。

1.2.2 最小生成树图的生成树不是唯一的,把具有权最小的生成树称为图G的最小生成树,即生成树中每条边上的权值之和达到最小。

如图1所示。

图1.网转化为最小生成树1.3 理解PRIM(普里姆)算法的基本思想1.3.1 PRIM算法(普里姆算法)的基本思想假设G =(V,E)是一个具有n个顶点的连通网,T=(U,TE)是G的最小生成树,其中U是T的顶点集,TE是T的边集,U和TE的初值均为空集。

最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)

最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)

最⼩⽣成树---普⾥姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)最⼩⽣成树的性质:MST性质(假设N=(V,{E})是⼀个连通⽹,U是顶点集V的⼀个⾮空⼦集,如果(u,v)是⼀条具有最⼩权值的边,其中u属于U,v属于V-U,则必定存在⼀颗包含边(u,v)的最⼩⽣成树)普⾥姆算法(Prim算法)思路:以点为⽬标构建最⼩⽣成树1.将初始点顶点u加⼊U中,初始化集合V-U中各顶点到初始顶点u的权值;2.根据最⼩⽣成树的定义:从n个顶点中,找出 n - 1条连线,使得各边权值最⼩。

循环n-1次如下操作:(1)从数组lowcost[k]中找到vk到集合U的最⼩权值边,并从数组arjvex[k] = j中找到该边在集合U中的顶点下标(2)打印此边,并将vk加⼊U中。

(3)通过查找邻接矩阵Vk⾏的各个权值,即vk点到V-U中各顶点的权值,与lowcost的对应值进⾏⽐较,若更⼩则更新lowcost,并将k存⼊arjvex数组中以下图为例#include<bits/stdc++.h>using namespace std;#define MAXVEX 100#define INF 65535typedef char VertexType;typedef int EdgeType;typedef struct {VertexType vexs[MAXVEX];EdgeType arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;void CreateMGraph(MGraph *G) {int m, n, w; //vm-vn的权重wscanf("%d %d", &G->numVertexes, &G->numEdges);for(int i = 0; i < G->numVertexes; i++) {getchar();scanf("%c", &G->vexs[i]);}for(int i = 0; i < G->numVertexes; i++) {for(int j = 0; j < G->numVertexes; j++) {if(i == j) G->arc[i][j] = 0;else G->arc[i][j] = INF;}}for(int k = 0; k < G->numEdges; k++) {scanf("%d %d %d", &m, &n, &w);G->arc[m][n] = w;G->arc[n][m] = G->arc[m][n];}}void MiniSpanTree_Prim(MGraph G) {int min, j, k;int arjvex[MAXVEX]; //最⼩边在 U集合中的那个顶点的下标int lowcost[MAXVEX]; // 最⼩边上的权值//初始化,从点 V0开始找最⼩⽣成树Tarjvex[0] = 0; //arjvex[i] = j表⽰ V-U中集合中的 Vi点的最⼩边在U集合中的点为 Vjlowcost[0] = 0; //lowcost[i] = 0表⽰将点Vi纳⼊集合 U ,lowcost[i] = w表⽰ V-U中 Vi点到 U的最⼩权值for(int i = 1; i < G.numVertexes; i++) {lowcost[i] = G.arc[0][i];arjvex[i] = 0;}//根据最⼩⽣成树的定义:从n个顶点中,找出 n - 1条连线,使得各边权值最⼩for(int i = 1; i < G.numVertexes; i++) {min = INF, j = 1, k = 0;//寻找 V-U到 U的最⼩权值minfor(j; j < G.numVertexes; j++) {// lowcost[j] != 0保证顶点在 V-U中,⽤k记录此时的最⼩权值边在 V-U中顶点的下标if(lowcost[j] != 0 && lowcost[j] < min) {min = lowcost[j];k = j;}}}printf("V[%d]-V[%d] weight = %d\n", arjvex[k], k, min);lowcost[k] = 0; //表⽰将Vk纳⼊ U//查找邻接矩阵Vk⾏的各个权值,与lowcost的对应值进⾏⽐较,若更⼩则更新lowcost,并将k存⼊arjvex数组中for(int i = 1; i < G.numVertexes; i++) {if(lowcost[i] != 0 && G.arc[k][i] < lowcost[i]) {lowcost[i] = G.arc[k][i];arjvex[i] = k;}}}int main() {MGraph *G = (MGraph *)malloc(sizeof(MGraph));CreateMGraph(G);MiniSpanTree_Prim(*G);}/*input:4 5abcd0 1 20 2 20 3 71 2 42 3 8output:V[0]-V[1] weight = 2V[0]-V[2] weight = 2V[0]-V[3] weight = 7最⼩总权值: 11*/时间复杂度O(n^2)克鲁斯卡尔算法(Kruskal算法)思路:以边为⽬标进⾏构建最⼩⽣成树在边集中依次寻找最⼩权值边,若构建是不形成环路(利⽤parent数组记录各点的连通分量),则将其添加到最⼩⽣成树中。

考研数据结构图的必背算法及知识点

考研数据结构图的必背算法及知识点

考研数据结构图的必背算法及知识点Prepared on 22 November 20201.最小生成树:无向连通图的所有生成树中有一棵边的权值总和最小的生成树问题背景:假设要在n个城市之间建立通信联络网,则连通n个城市只需要n—1条线路。

这时,自然会考虑这样一个问题,如何在最节省经费的前提下建立这个通信网。

在每两个城市之间都可以设置一条线路,相应地都要付出一定的经济代价。

n个城市之间,最多可能设置n(n-1)/2条线路,那么,如何在这些可能的线路中选择n-1条,以使总的耗费最少呢分析问题(建立模型):可以用连通网来表示n个城市以及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价。

对于n个顶点的连通网可以建立许多不同的生成树,每一棵生成树都可以是一个通信网。

即无向连通图的生成树不是唯一的。

连通图的一次遍历所经过的边的集合及图中所有顶点的集合就构成了该图的一棵生成树,对连通图的不同遍历,就可能得到不同的生成树。

图G5无向连通图的生成树为(a)、(b)和(c)图所示:G5G5的三棵生成树:可以证明,对于有n个顶点的无向连通图,无论其生成树的形态如何,所有生成树中都有且仅有n-1条边。

最小生成树的定义:如果无向连通图是一个网,那么,它的所有生成树中必有一棵边的权值总和最小的生成树,我们称这棵生成树为最小生成树,简称为最小生成树。

最小生成树的性质:假设N=(V,{E})是个连通网,U是顶点集合V的一个非空子集,若(u,v)是个一条具有最小权值(代价)的边,其中,则必存在一棵包含边(u,v)的最小生成树。

解决方案:两种常用的构造最小生成树的算法:普里姆(Prim)和克鲁斯卡尔(Kruskal)。

他们都利用了最小生成树的性质1.普里姆(Prim)算法:有线到点,适合边稠密。

时间复杂度O(N^2)假设G=(V,E)为连通图,其中V为网图中所有顶点的集合,E为网图中所有带权边的集合。

普里姆迪杰斯特拉克鲁斯卡尔弗洛伊德比较

普里姆迪杰斯特拉克鲁斯卡尔弗洛伊德比较

一、Prim算法与Dijkstra算法:1、相同:1)都利用了顶点集U和V-U中顶点的最小值;2)都有一出发点;3)每次都是选出最小的值并入U中以作为过渡顶点,而不再求其最小;4)都涉及最短问题;5)它们都是从一个原始顶点开始将顶点一个个按一定顺序转移到所求终点中。

6)都用到了辅助向量;7)都从顶点出发,并在过程中都依据了顶点;8)都包含其顶点连通分量;9)都是对网进行操作;10)用找到的路径将顶点连接起来都是树;2、相异:1)普里姆算法从顶点集U中任一顶点出发到V—U中顶点,迪杰斯特拉算法从源点出发通过顶点U到找到V—U中顶点的最小值;2)普里姆算法的出发点是算法的开始点;而迪杰斯特拉算法的出发点是求最短路径的源点;3)普里姆算法用lowcost数组,而迪杰斯特拉算法用D[ j ]=Min{D[ i ]|v i属于顶点集V-S}4)普里姆算法解决最小生成树,迪杰斯特拉算法解决最短路径;5)普里姆算法是顺着已找到的顶点找其余应并入U中的顶点,而迪杰斯特拉算法是顺着顶点去找其余顶点到源点的最短路径;6)普里姆算法的最短是两个顶点集间的最短,而迪杰斯特拉算法的最短是某点通过一个顶点集U到源点的最短。

7)普里姆算法的最短是两个顶点间的最短,而迪杰斯特拉算法的最短是某点到源点的最短。

8)普法无需按最短的并入,它寻找并入U的点的依据是在U和V-U之间的最短路径。

9)迪法在找到最短路径后,还要对其余结点的当前最短路径进行修改,而普法则不进行修改。

10)普法是从顶点集的思路出发,而迪法则是按路径长度递增思路出发。

11)普法的出发点是任意的,而迪法的出发点是规定的。

12)普法在执行过程中不改变两点间的权值,而迪法在执行过程中会求出一个或者是两点的权值或者是权值之和作为最短的路径;13)迪法具有方向性,而普法则可以不具有;14)二、Prim算法与Krukal算法:1、相同:1)都是找最小生成树的方法;2)都用到了MST性质;3)算法执行前都把n个结点看成是n棵树,而算法完成后,都成为了一棵树。

普里姆和克鲁斯卡尔算法

普里姆和克鲁斯卡尔算法

前言从学习《数据结构》这门课程开始,我已发现了学习算法的乐趣,在学习这门课的过程中也学到了许多计算机应用基础知识,对计算机的机体也有了一个初步的了解,又在课余时间阅读了大量有关算法设计与分析的图书,在此基础上,利用贪心算法,编写了一个用prim 和kruskal算法求解最小生成树,也以此检验自己一学期所学成果,加深对算法设计与分析这门课程的理解,由于所学知识有限,难免有些繁琐和不完善之处,下面向大家介绍此程序的设计原理,方法,内容及设计的结果。

本程序是在windows 环境下利用Microsoft Visual C++ 6.0所编写的,主要利用贪心算法的思想,以及数组,for语句的循环,if语句的嵌套,运用以上所学知识编写出的prim和kruskal算法求解最小生成树,在输入其边的起始位置,种植位置以及权值后,便可分别输出此网的prim和kruskal算法最小生成树的边的起始位置,终止位置以及权值。

正文2.1 设计方法和内容一.软件环境:Microsoft Visual C++ 6.0二.详细设计思想:所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择。

也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

贪心算法的基本思路如下:1.建立数学模型来描述问题。

2.把求解的问题分成若干个子问题。

3.对每一子问题求解,得到子问题的局部最优解。

4.把子问题的解局部最优解合成原来解问题的一个解。

1.Prim(普里姆)算法思想无向网的最小生成树问题此算法的思想是基于点的贪心,力求从源点到下一个点的距离最短,以此来构建临接矩阵,所以此算法的核心思想是求得源点到下一个点的最短距离,下面具体解释如何求此最短距离:在图中任取一个顶点k作为开始点,令集合U={k},集合w=V-U,其中v为图中所有顶点的集合,然后找出:一个顶点在集合U中,另一个顶点在集合W中的所有边中,权值最短的一条边,,并将该边顶点全部加入集合U中,并从W中删去这些顶点,然后重新调整U中顶点到W中顶点的距离,使之保持最小,在重复此过程,直到W为空集为止,求解过程如下:由图可知最小生成树的步骤,假设开始顶点就选为1,故首先有u={1},w={2,3,4,5}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

/*
用Prim算法求最小生成树
*/
#include<stdio.h>
#include<malloc.h>
#define MAXV100
#define INF10000//定义最大值,表括示两个结点着无路径可走
typedef int InfoType;
typedef struct
{
int no;
InfoType info;//顶点其他信息,这里用于存放权值
}VertexType;
typedef struct
{
int edges[MAXV][MAXV];//邻接矩阵
int n;
int e;//顶点数和弧数
VertexType vexs[MAXV];//存放顶点的信息}MGraph;
//输出邻接阵
void DispMat(MGraph g)
{
int i,j;
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++)
{
if(g.edges[i][j]==INF)
printf("%3s","*");
else
printf("%3d",g.edges[i][j]);
}
printf("\n");
}
}
void Prim(MGraph g,int v)
{
int lowcost[MAXV],min,n=g.n;
int closest[MAXV],i,j,k;
int falsh[6]={1,1,1,1,1,1}; //标治着结点被访问
falsh[v]=0;//被访问过的赋值为0
for(i=0;i<n;i++)
{
lowcost[i]=g.edges[v][i];
closest[i]=v;
}
for(i=1;i<n;i++)
{
min=INF;
for(j=0;j<n;j++)
{
if(falsh[j]&&lowcost[j]<min)
{
min=lowcost[j];
k=j;
}
}
falsh[k]=0;
printf("边(%d %d)权为a:%d\n",closest[k],k,min);
lowcost[k]=0;//标记已经加入U
/*下面for的句式的功能是在已生成最小树的结点到未生成最小生成树的结点的最小路·径*/
for(j=0;j<n;j++)
{
if(g.edges[k][j]!=0&&g.edges[k][j]<lowcost[j])
{
lowcost[j]=g.edges[k][j];
closest[j]=k;
}
}
}
}
void main()
{
int i,j,u=3;
MGraph g;
int A[MAXV][11];
g.n=6;
g.e=10;
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++)
{
A[i][j]=INF;
}
}
A[0][1]=5;A[0][2]=8;A[0][3]=7;A[0][5]=3; A[1][2]=4;
A[2][3]=5;A[2][5]=9;
A[3][4]=5;
A[4][5]=1;
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++)
{
A[j][i]=A[i][j];
}
}
for(i=0;i<g.n;i++)
{
for(j=0;j<g.n;j++)
{
g.edges[i][j]=A[i][j];
}
}
printf("\n");
printf("图的邻接矩阵:\n");
DispMat(g);
printf("\n");
printf("普里姆·算法求解结果?:\n");
Prim(g,0);
printf("\n");
}
运行结果:。

相关文档
最新文档