最小生成树 Prim算法实现C++

合集下载

c++ prim函数

c++ prim函数

c++ prim函数
C++的STL库中有一个非常重要的函数——prim函数。

prim函数是一种用于求解最小生成树问题的算法,可以在图中找到一棵包含全部节点的最小权值树。

prim函数的基本思想是从任意一个节点开始,不断添加与已有节点相连的权值最小的节点,直到所有节点都被加入为止。

具体实现过程如下:
1. 初始化一个集合S,包含任意一个节点v。

2. 初始化一个set,用于保存所有与集合S相连的节点和相应的边权值,根据边权值从小到大排序。

3. 从set中取出权值最小的边(u,w),如果u不在集合S中,则将u加入集合S,并将(u,w)加入最小生成树的边集中。

4. 将所有与u相连的节点v及其边权值添加到set中,如果v 已经在S中,则从set中删除。

5. 重复步骤3和4,直到集合S包含所有节点为止。

prim函数的时间复杂度为O(ElogV),其中E表示边数,V表示节点数。

它是一种贪心算法,每次选择当前情况下的最优解,但并不保证一定能够得到全局最优解。

- 1 -。

C语言实现最小生成树构造算法

C语言实现最小生成树构造算法

C语⾔实现最⼩⽣成树构造算法最⼩⽣成树最⼩⽣成树(minimum spanning tree)是由n个顶点,n-1条边,将⼀个连通图连接起来,且使权值最⼩的结构。

最⼩⽣成树可以⽤Prim(普⾥姆)算法或kruskal(克鲁斯卡尔)算法求出。

我们将以下⾯的带权连通图为例讲解这两种算法的实现:注:由于测试输⼊数据较多,程序可以采⽤⽂件输⼊Prim(普⾥姆)算法时间复杂度:O(N^2)(N为顶点数)prim算法⼜称“加点法”,⽤于边数较多的带权⽆向连通图⽅法:每次找与之连线权值最⼩的顶点,将该点加⼊最⼩⽣成树集合中注意:相同权值任选其中⼀个即可,但是不允许出现闭合回路的情况。

代码部分通过以下步骤可以得到最⼩⽣成树:1.初始化:lowcost[i]:表⽰以i为终点的边的最⼩权值,当lowcost[i]=0表⽰i点加⼊了MST。

mst[i]:表⽰对应lowcost[i]的起点,当mst[i]=0表⽰起点i加⼊MST。

由于我们规定最开始的顶点是1,所以lowcost[1]=0,MST[1]=0。

即只需要对2~n进⾏初始化即可。

#define MAX 100#define MAXCOST 0x7fffffffint graph[MAX][MAX];void prim(int graph[][MAX], int n){int lowcost[MAX];int mst[MAX];int i, j, min, minid, sum = 0;for (i = 2; i <= n; i++){lowcost[i] = graph[1][i];//lowcost存放顶点1可达点的路径长度mst[i] = 1;//初始化以1位起始点}mst[1] = 0;2.查找最⼩权值及路径更新定义⼀个最⼩权值min和⼀个最⼩顶点ID minid,通过循环查找出min和minid,另外由于规定了某⼀顶点如果被连⼊,则lowcost[i]=0,所以不需要担⼼重复点问题。

求出下图的最小生成树

求出下图的最小生成树

求出下图的最小生成树解:MATLAB程序:% 求图的最小生成树的prim算法。

% result的第一、二、三行分别表示生成树边的起点、终点、权集合% p——记录生成树的的顶点,tb=V\pclc;clear;% a(1,2)=50; a(1,3)=60;% a(2,4)=65; a(2,5)=40;% a(3,4)=52;a(3,7)=45;% a(4,5)=50; a(4,6)=30;a(4,7)=42;% a(5,6)=70;% a=[a;zeros(2,7)];e=[1 2 20;1 4 7;2 3 18;2 13 8;3 5 14;3 14 14;4 7 10;5 6 30;5 9 25;5 10 9;6 10 30;6 11 30;7 8 2;7 13 5;8 9 4;8 14 2;9 10 6;9 14 3;10 11 11;11 12 30];n=max([e(:,1);e(:,2)]); % 顶点数m=size(e,1); % 边数M=sum(e(:,3)); % 代表无穷大a=zeros(n,n);for k=1:ma(e(k,1),e(k,2))=e(k,3);enda=a+a';a(find(a==0))=M; % 形成图的邻接矩阵result=[];p=1; % 设置生成树的起始顶点tb=2:length(a); % 设置生成树以外顶点while length(result)~=length(a)-1 % 边数不足顶点数-1temp=a(p,tb);temp=temp(:); % 取出与p关联的所有边d=min(temp); % 取上述边中的最小边[jb,kb]=find(a(p,tb)==d); % 寻找最小边的两个端点(可能不止一个)j=p(jb(1));k=tb(kb(1)); % 确定最小边的两个端点result=[result,[j;k;d]]; % 记录最小生成树的新边p=[p,k]; % 扩展生成树的顶点tb(find(tb==k))=[]; % 缩减生成树以外顶点endresult % 显示生成树(点、点、边长)weight=sum(result(3,:)) % 计算生成树的权程序结果:result =1 4 7 8 14 7 9 13 10 10 14 10 11 4 7 8 14 9 13 102 5 113 6 12 7 10 2 2 3 5 6 8 9 11 14 30 30 weight =137附图最小生成树的权是137。

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的初值均为空集。

c语言prim算法

c语言prim算法

c语言prim算法摘要:1.C 语言和Prim 算法简介2.Prim 算法的应用3.Prim 算法的实现4.结论正文:一、C 语言和Prim 算法简介C 语言是一种广泛应用的计算机编程语言,以其高效性和灵活性著称。

它被广泛应用于操作系统、嵌入式系统、游戏开发等领域。

Prim 算法是一种用于解决无向图最小生成树问题的贪心算法。

它的基本思想是从一个顶点开始,不断地寻找与当前生成树距离最近的顶点,将其加入到生成树中,直到所有顶点都加入到生成树中为止。

二、Prim 算法的应用Prim 算法在图论中有着广泛的应用,例如在网络设计、最短路径问题、数据压缩等领域。

在网络设计中,可以用Prim 算法来找到一个网络的最小生成树,从而减少网络的成本。

在最短路径问题中,Prim 算法可以用来找到一个图中两点之间的最短路径。

在数据压缩中,Prim 算法可以用来找到一个图的最小生成树,从而将图压缩成一个更小的表示。

三、Prim 算法的实现下面是一个简单的C 语言实现的Prim 算法:```c#include <stdio.h>#include <stdlib.h>#include <stdbool.h>typedef struct node {int vertex;int weight;} node;typedef struct graph {int vertices;node **adjList;} graph;void add_edge(graph *g, int src, int dest, int weight) { g->adjList[src] = (node*) malloc(sizeof(node));g->adjList[src]->vertex = dest;g->adjList[src]->weight = weight;g->adjList[dest] = (node*) malloc(sizeof(node));g->adjList[dest]->vertex = src;g->adjList[dest]->weight = weight;}bool is_valid_edge(graph *g, int src, int dest) {return g->adjList[src]!= NULL && g->adjList[dest]!= NULL; }int prim_min_tree_weight(graph *g) {int sum = 0;int *dist = (int*) calloc(g->vertices, sizeof(int));for (int i = 0; i < g->vertices; i++) {dist[i] = INT_MAX;}int min_weight = INT_MAX;int root = -1;while (root == -1) {for (int i = 0; i < g->vertices; i++) {if (dist[i] == INT_MAX) {continue;}for (int j = 0; j < g->vertices; j++) {if (is_valid_edge(g, i, j) && dist[j] > dist[i] + g->adjList[i]->weight) {dist[j] = dist[i] + g->adjList[i]->weight;if (min_weight > dist[j]) {min_weight = dist[j];root = j;}}}}}for (int i = 0; i < g->vertices; i++) { sum += dist[i];}free(dist);return min_weight;}int main() {graph g = {3, NULL};add_edge(&g, 0, 1, 4);add_edge(&g, 0, 2, 3);add_edge(&g, 1, 2, 1);add_edge(&g, 1, 3, 2);add_edge(&g, 2, 3, 4);printf("Minimum tree weight: %d ", prim_min_tree_weight(&g));return 0;}```四、结论C 语言和Prim 算法的结合可以有效地解决图论中的最小生成树问题。

PAT 数据结构 06-图6. 公路村村通(30)Prim最小生成树算法

PAT 数据结构 06-图6. 公路村村通(30)Prim最小生成树算法

PAT 数据结构 06-图6. 公路村村通(30)Prim最小生成树算法现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式说明:输入数据包括城镇数目正整数N(<=1000)和候选道路数目M(<=3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。

为简单起见,城镇从1到N编号。

输出格式说明:输出村村通需要的最低成本。

如果输入数据不足以保证畅通,则输出-1,表示需要建设更多公路。

样例输入与输出:用Prim最小生成树算法来写:已吸收的结点为集合AB,一开始只有1号结点。

未吸收的结点为集合UD,一开始包含除1号外的所有结点。

每次以最小边的代价将UD中的一个结点吸收到AB。

一开始想到可以用穷举的方法写,当AB集合有k个结点时,UD集合有N-K 个,穷举两个集合的所有可能连线,通常来说遍历的效率较低,说得形象点,k 每次变化时,每次都要判断1号结点都要与UD集合中的所有结点是否有边,显然第一次之后的判断都是多余的。

从这个角度来想,我们每次只要判断AB中最新的一个结点与UD中所有结点是否有边即可。

为了便于操作,定义结点结构体如下面代码所示。

由于我是第一次写该算法,多加了前驱结点proNode,用于输出具体的生成树。

该变量在本题中是多余的,可以去掉。

[cpp]view plain copy print?1./*2015.7.16cyq*/2.//Prim最小生成树算法3.#include<iostream>4.#include<vector>5.#include<fstream>6.#include<algorithm>7.std;8.9.int MAX=2147483647;10.//ifstream fin("case1.txt");11.//#define cin fin12.13.node{14.int num;//结点序号15.int weight;//能连通到已确定子图的最小边16.int preNode;//最小边依附的结点,用于输出具体生成树17.node():num(-1),weight(-1),preNode(-1){}18.node(int n,int wei,int preN):num(n),weight(wei),preNode(preN){}19.bool operator<(node&a){20.weight<a.weight;21.}22.};23.24.int main(){25.int N,M;26.cin>>N>>M;27.vector<vector<int>>edges(N+1,vector<int>(N+1,-1));//-1表示不连通28.int a,b,c;29.(M--){30.cin>>a>>b>>c;31.edges[a][b]=c;32.edges[b][a]=c;33.}34.35.vector<node>AB;//已吸收的点,一开始只有结点136.AB.push_back(node(1,0,-1));//37.vector<node>UD(N-1);//未吸收的点38.(int i=0;i<N-1;i++){39.UD[i].num=i+2;//编号2到N40.int tmp=edges[1][UD[i].num];41.(tmp>0){//能连到结点1的结点42.UD[i].weight=tmp;43.UD[i].preNode=1;44.}{//不能连到结点1的结点45.UD[i].weight=MAX;46.UD[i].preNode=-1;47.}48.}49.int totalLength=0;50.//vector<pair<int,int>>result;//用于输出具体生成树51.(!UD.empty()){52.sort(UD.begin(),UD.end());53.node cur=UD[0];//取出能以最小代价吸收的点54.UD.erase(UD.begin());55.(cur.weight==MAX){56.cout<<"-1"<<endl;57.0;58.}59.totalLength+=cur.weight;60.//result.push_back(make_pair(cur.num,cur.preNode));61.(auto it=UD.begin();it!=UD.end();++it){//用该点修正未吸收的点62.int w=edges[cur.num][(*it).num];63.(w>0){64.(w<(*it).weight){65.(*it).weight=w;66.(*it).preNode=cur.num;67.}68.}69.}70.}71.cout<<totalLength<<endl;72.//for(auto it=result.begin();it!=result.end();++it){//输出最小生成树73.//cout<<(*it).first<<""<<(*it).second<<""<<edges[(*it).first][(*it).second]<<endl;74.//}75.0;76.}事实上,可以进一步把UD集合分成两个集合,第一个集合中的点与AB相邻,第二个集合的点与AB不相邻,尚未探测到。

prim算法c语言

prim算法c语言

prim算法c语言什么是Prim算法?Prim算法,也叫普里姆算法,是一种用于求解最小生成树的贪心算法。

最小生成树是指在一个无向连通图中,连接所有节点且边权值之和最小的树。

Prim算法的基本思想是从一个起始节点开始,每次选择与当前已经构建好的部分形成的子图相连的、权值最小的边所连接的节点,并将该节点加入到已经构建好的部分中。

直到所有节点都被加入到已经构建好的部分中,此时得到了一棵最小生成树。

Prim算法步骤1. 选定一个起点作为已经构建好的部分。

2. 将与该起点相连且未被访问过的边加入到候选集合中。

3. 从候选集合中选择一条权值最小的边连接到未被访问过的节点,并将该节点加入到已经构建好的部分中。

4. 将新加入节点所连接且未被访问过的边加入到候选集合中。

5. 重复步骤3和步骤4,直至所有节点都被加入到已经构建好的部分中。

Prim算法C语言实现下面给出Prim算法C语言实现代码:```#include <stdio.h>#include <stdlib.h>#include <limits.h>#define MAX_VERTICES 100#define INF INT_MAXtypedef struct {int weight;int visited;} Vertex;typedef struct {int vertices[MAX_VERTICES][MAX_VERTICES]; int num_vertices;} Graph;void init_graph(Graph *graph, int num_vertices) {graph->num_vertices = num_vertices;for (int i = 0; i < num_vertices; i++) {for (int j = 0; j < num_vertices; j++) {graph->vertices[i][j] = INF;}}}void add_edge(Graph *graph, int u, int v, int weight) { graph->vertices[u][v] = weight;graph->vertices[v][u] = weight;}void prim(Graph *graph) {Vertex vertices[MAX_VERTICES];for (int i = 0; i < graph->num_vertices; i++) {vertices[i].weight = INF;vertices[i].visited = 0;}vertices[0].weight = 0;for (int i = 0; i < graph->num_vertices - 1; i++) {// 找到未访问过的权值最小的节点int min_vertex_index = -1;for (int j = 0; j < graph->num_vertices; j++) {if (!vertices[j].visited && (min_vertex_index == -1 || vertices[j].weight < vertices[min_vertex_index].weight)) { min_vertex_index = j;}}// 将该节点标记为已访问vertices[min_vertex_index].visited = 1;// 更新与该节点相连的未访问过的节点的权值for (int j = 0; j < graph->num_vertices; j++) {if (!vertices[j].visited && graph->vertices[min_vertex_index][j] < vertices[j].weight) {vertices[j].weight = graph->vertices[min_vertex_index][j];}}}// 输出最小生成树printf("Minimum Spanning Tree:\n");for (int i = 1; i < graph->num_vertices; i++) {printf("%d - %d (%d)\n", i, (i - 1), vertices[i].weight); }}int main() {Graph graph;init_graph(&graph, 6);add_edge(&graph, 0, 1, 6);add_edge(&graph, 0, 2, 1);add_edge(&graph, 0, 3, 5);add_edge(&graph, 1, 4, 3);add_edge(&graph, 2, 4, 5);add_edge(&graph, 2, 3, 5);add_edge(&graph, 2, 5, 4);add_edge(&graph, 3 ,5 ,2);prim(&graph);return EXIT_SUCCESS;}```代码解释- 定义了Vertex结构体,用于存储节点的权值和访问状态。

c++普里姆算法最小生成树

c++普里姆算法最小生成树

c++普里姆算法最小生成树普姆算法 (Prim"s 算法) 是一种用于寻找最小生成树的算法。

它的时间复杂度为 $O(Elog E)$,其中 $E$ 是边数。

下面是 C++ 普姆算法的实现:```cpp#include <iostream>#include <vector>#include <cmath>using namespace std;// 定义边数const int E = 100010;// 定义最小生成树边权数组vector<int> adj[E];int weight[E];// 普姆算法int Prim(int u, vector<bool> &visited) {// 如果当前节点已经被访问过,则直接返回当前节点的值if (visited[u]) {return u;}// 计算当前节点到其他节点的最短路for (int v : adj[u]) {if (!visited[v]) {// 将当前节点添加到最小生成树中weight[u] += weight[v];adj[u].push_back(v);}}// 如果当前节点到其他节点的最短路长度小于当前的权值,则将当前节点的权值更新为最短路长度for (int v : adj[u]) {if (!visited[v]) {int dist = sqrt(pow(weight[u], 2) + pow(weight[v], 2)); weight[u] = dist;}}// 返回当前节点的值return u;}// 计算最小生成树vector<int> PrimTree(vector<int> &adj, int u) {// 如果当前节点已经被访问过,则直接返回当前节点的值vector<int> tree(adj.size(), -1);tree[u] = 0;// 辅助数组,记录每个节点到其他节点的最短路vector<int> pd(adj.size(), -1);for (int v : adj[u]) {if (!pd[v]) {pd[v] = u;}}// 循环遍历每个节点,并将当前节点添加到最小生成树中 for (int v = 0; v < adj.size(); v++) {int pdv = pd[v];if (pdv != -1 && weight[v] < weight[pdv]) {tree[v] = pdv;}}return tree;}int main() {// 读入边数cin >> E;// 读入边权数组for (int i = 0; i < E; i++) {cin >> weight[i];}// 初始化邻接表for (int i = 0; i < E; i++) {for (int j = 0; j < E; j++) {if (weight[i] < weight[j]) {adj[i].push_back(j);}}}// 计算最小生成树vector<int> tree = PrimTree(adj, 0);// 输出最小生成树for (int i = 0; i < tree.size(); i++) {cout << tree[i] << " ";}cout << endl;return 0;}```在上述代码中,我们首先定义了边数 `E`,然后读入边权数组`weight`。

最小生成树(普里姆算法)

最小生成树(普里姆算法)

最⼩⽣成树(普⾥姆算法):所谓⽣成树,就是n个点之间连成n-1条边的图形。

⽽最⼩⽣成树,就是权值(两点间直线的值)之和的最⼩值。

⾸先,要⽤⼆维数组记录点和权值。

如上图所⽰⽆向图:int map[7][7];map[1][2]=map[2][1]=4;map[1][3]=map[3][1]=2;......然后再求最⼩⽣成树。

具体⽅法是:1.先选取⼀个点作起始点,然后选择它邻近的权值最⼩的点(如果有多个与其相连的相同最⼩权值的点,随便选取⼀个)。

如1作为起点。

visited[1]=1;pos=1;//⽤low[]数组不断刷新最⼩权值,low[i](0<i<=点数)的值为:i点到邻近点(未被标记)的最⼩距离。

low[1]=0; //起始点i到邻近点的最⼩距离为0low[2]=map[pos][2]=4;low[3]=map[pos][3]=2;low[4]==map[pos][4]=3;low[5]=map[pos][5]=MaxInt; //⽆法直达low[6]=map[pos][6]=MaxInt;2.再在伸延的点找与它邻近的两者权值最⼩的点。

//low[]以3作当前位置进⾏更新visited[3]=1;pos=3;low[1]=0; //已标记,不更新low[2]=map[1][2]=4; //⽐5⼩,不更新low[3]=2; //已标记,不更新low[4]=map[1][4]=3; //⽐1⼤,更新后为:low[4]=map[3][4]=1;low[5]=map[1][5]=MaxInt;//⽆法直达,不更新low[6]=map[1][6]=MaxInt;//⽐2⼤,更新后为:low[6]=map[3][6]=2;3.如此类推...当所有点都连同后,结果最⽣成树如上图所⽰。

所有权值相加就是最⼩⽣成树,其值为2+1+2+4+3=12。

⾄于具体代码如何实现,现在结合POJ1258例题解释。

c语言prim算法

c语言prim算法

c语言prim算法Prim算法是一种用于求解最小生成树问题的算法,它通过逐步选择与当前生成树相邻且权重最小的边来逐步构建最小生成树。

下面是使用C语言实现Prim算法的示例代码:```c#include <stdio.h>#include <limits.h>#define V 5 // 图中顶点的数量int minKey(int key[], int mstSet[]) {int min = INT_MAX, min_index;for (int v = 0; v < V; v++) {if (mstSet[v] == 0 && key[v] < min) {min = key[v];min_index = v;}}return min_index;}void printMST(int parent[], int graph[V][V]) {printf("Edge \tWeight\n");for (int i = 1; i < V; i++) {printf("%d - %d \t%d\n", parent[i], i, graph[i][parent[i]]); }}void primMST(int graph[V][V]) {int parent[V]; // 存放最小生成树的边int key[V]; // 存放顶点的键值int mstSet[V]; // 标记顶点是否已包含在最小生成树中for (int i = 0; i < V; i++) {key[i] = INT_MAX;mstSet[i] = 0;}key[0] = 0;parent[0] = -1;for (int count = 0; count < V - 1; count++) {int u = minKey(key, mstSet);mstSet[u] = 1;for (int v = 0; v < V; v++) {if (graph[u][v] && mstSet[v] == 0 && graph[u][v] < key[v]) {parent[v] = u;key[v] = graph[u][v];}}}printMST(parent, graph);}int main() {int graph[V][V] = {{0, 2, 0, 6, 0},{2, 0, 3, 8, 5},{0, 3, 0, 0, 7},{6, 8, 0, 0, 9},{0, 5, 7, 9, 0}};primMST(graph);return 0;}```此示例实现了Prim算法来求解给定图形的最小生成树,并且在控制台打印出了所得到的最小生成树的边及其权重。

通过使用prim算法(反圈法)求解最小支撑树问题

通过使用prim算法(反圈法)求解最小支撑树问题

一.实验目的通过使用prim算法(反圈法)求解最小支撑树问题..二.实验内容设图G =(V,E),其生成树的顶点集合为U。

①.把v0放入U。

②.在所有u∈U,v∈V-U的边(u,v)∈E中找一条最小权值的边,加入生成树。

③.把②找到的边的v加入U集合。

如果U集合已有n个元素,则结束,否则继续执行②。

其算法的时间复杂度为O(n^2)Prim算法实现:图用邻接阵表示,路径不通用无穷大表示,在计算机中可用一个大整数代替。

采用堆,可以将复杂度降为O(m log n),如果采用Fibonaci堆可以将复杂度降为O(n log n + m)三.使用环境Windows XP 环境下MATLAB 编写四.调试过程程序如下:#include<stdio.h>#include<stdlib.h>#include<string.h>#define INFINITY 1000#define max_name 50#define max_vertex_num 50typedef char vertex[max_name];//顶点名字串typedef int adjMatrix[max_vertex_num][max_vertex_num];//邻接距阵typedef struct{vertex adjvex; //邻接矩阵int lowcost; //权值}close[max_vertex_num];//定义一个结构以便在后面closedge 使用typedef struct//定义图{vertex vexs[max_vertex_num]; //顶点集adjMatrix arcs; //边int vexnum,arcnum;//点个数,边个数}MGraph;int LocateVex(MGraph G,vertex u)//若G中存在顶点u,则返回该点在图中位置;否则返回其他信息;{int i;for(i=0;i<G.vexnum;++i)if(strcmp(u,G.vexs[i])==0)return i;return 1;}void CreateGraph(MGraph &G){int i,j,k,w;vertex v1,v2;printf("输入无向图顶点数和边数: \n");scanf("%d %d",&G.vexnum,&G.arcnum);printf("输入各顶点的值:\n", G.vexnum);for(i=0;i<G.vexnum;++i) //构造顶点集scanf("%s",&G.vexs[i]);for(i=0;i<G.vexnum;++i) //初始化邻接方阵for(j=0;j<G.vexnum;++j)G.arcs[i][j]=INFINITY;printf("输入一条边依附的顶点及权值:\n",G.arcnum);//输入一条边依附的顶点及权值for(k=0;k<G.arcnum;++k){scanf("%s%s%d",v1,v2,&w);i=LocateVex(G,v1);//v1在图中位置j=LocateVex(G,v2);//v2在图中位置G.arcs[i][j]=G.arcs[j][i]=w; //置于对称弧}}int minimum(close c,MGraph G)//求出下一个节点第k个顶点{int i=0,j,k,min;min=INFINITY;//初始化k=-1;for(j=0;j<=G.vexnum;j++)//求最小if(c[j].lowcost<min&&c[j].lowcost>0){min=c[j].lowcost;k=j;}return k;}void PRIM(MGraph G,vertex u){int i,j,k=0;close closedge;//一个结构bool isbreak=false;k=LocateVex(G,u);//u在图中位置返回G.vexs[i]中下标for(j=0;j<=G.vexnum;++j) //辅助数组初始化closedge从O 开始{if(j!=k)//没有自己到自己的closedge[k].lowcost=0;strcpy(closedge[j].adjvex,u);closedge[j].lowcost=G.arcs[k][j];//列}int flag[1000];flag[0]=0;int count=1;for(i=1;i<G.vexnum;++i){k=minimum(closedge,G);if(k==-1){isbreak=true;break;}printf("%s-%s%d\n",closedge[k].adjvex,G.vexs[k],G.arcs[k][LocateVex(G,closedge[k].adjvex)]); //输出生成树的边closedge[k].lowcost=0; // 第k个顶点并入U集flag[count]=k;count++;for(j=0;j<G.vexnum;++j)if(G.arcs[k][j]<closedge[j].lowcost)//新顶点并入U后重新选择最小边{strcpy(closedge[j].adjvex,G.vexs[k]);closedge[j].lowcost=G.arcs[k][j];}}if(isbreak){printf("此图不连通,无最小支撑树!\n访问过的点为:\n");for(i=0;i<count;i++){printf("%s ",G.vexs[flag[i]]);}printf("\n");}}void main(){MGraph G;CreateGraph(G);printf("最小生成树的各条边为: \n");PRIM(G,G.vexs[0]);}五.实验结果此处給出两个赋权图, 用prim算法找出赋权图上的最小树.图1结果如下:注释 :图1中有7个点10条边, 最后结果输出最小生成树为:图1最小权值W=5+1+2+3+4+1= 16图2结果如下:注释 :图2中有7个点10条边,但较图1(4-5)(5-6)无边相連,固输入权值为0.所以结果出现了两个連通子图.结果如下:而整个图2不連通,无最小支撑树.六.实验总结1.无向图的生成树就是从图的边集中选择一些边,使得这些边构成一个连通无环图,也就是树。

数据结构之最小生成树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中包含了最⼩⽣成树中的所有边。

代码实现1. 思想逻辑 (1)以⽆向图的某个顶点(A)出发,计算所有点到该点的权重值,若⽆连接取最⼤权重值#define INF (~(0x1<<31)) (2)找到与该顶点最⼩权重值的顶点(B),再以B为顶点计算所有点到改点的权重值,依次更新之前的权重值,注意权重值为0或⼩于当前权重值的不更新,因为1是⼀当找到最⼩权重值的顶点时,将权重值设为了0,2是会出现⽆连接的情况。

(3)将上述过程⼀次循环,并得到最⼩⽣成树。

2. Prim算法// Prim最⼩⽣成树void Prim(int nStart){int i = 0;int nIndex=0; // prim最⼩树的索引,即prims数组的索引char cPrims[MAX]; // prim最⼩树的结果数组int weights[MAX]; // 顶点间边的权值cPrims[nIndex++] = m_mVexs[nStart].data;// 初始化"顶点的权值数组",// 将每个顶点的权值初始化为"第start个顶点"到"该顶点"的权值。

for (i = 0; i < m_nVexNum; i++){weights[i] = GetWeight(nStart, i);}for (i = 0; i < m_nVexNum; i ++){if (nStart == i){continue;}int min = INF;int nMinWeightIndex = 0;for (int k = 0; k < m_nVexNum; k ++){if (weights[k]!= 0 && weights[k] < min){min = weights[k];nMinWeightIndex = k;}}// 找到下⼀个最⼩权重值索引cPrims[nIndex++] = m_mVexs[nMinWeightIndex].data;// 以找到的顶点更新其他点到该点的权重值weights[nMinWeightIndex]=0;int nNewWeight = 0;for (int ii = 0; ii < m_nVexNum; ii++){nNewWeight = GetWeight(nMinWeightIndex, ii);// 该位置需要特别注意if (0 != weights[ii] && weights[ii] > nNewWeight){weights[ii] = nNewWeight;}}for (i = 1; i < nIndex; i ++){int min = INF;int nVexsIndex = GetVIndex(cPrims[i]);for (int kk = 0; kk < i; kk ++){int nNextVexsIndex = GetVIndex(cPrims[kk]);int nWeight = GetWeight(nVexsIndex, nNextVexsIndex);if (nWeight < min){min = nWeight;}}nSum += min;}// 打印最⼩⽣成树cout << "PRIM(" << m_mVexs[nStart].data <<")=" << nSum << ": ";for (i = 0; i < nIndex; i++)cout << cPrims[i] << "";cout << endl;}3. 全部实现#include "stdio.h"#include <iostream>using namespace std;#define MAX 100#define INF (~(0x1<<31)) // 最⼤值(即0X7FFFFFFF)class EData{public:EData(char start, char end, int weight) : nStart(start), nEnd(end), nWeight(weight){} char nStart;char nEnd;int nWeight;};// 边struct ENode{int nVindex; // 该边所指的顶点的位置int nWeight; // 边的权重ENode *pNext; // 指向下⼀个边的指针};struct VNode{char data; // 顶点信息ENode *pFirstEdge; // 指向第⼀条依附该顶点的边};// ⽆向邻接表class listUDG{public:listUDG(){};listUDG(char *vexs, int vlen, EData **pEData, int elen){m_nVexNum = vlen;m_nEdgNum = elen;// 初始化"邻接表"的顶点for (int i = 0; i < vlen; i ++){m_mVexs[i].data = vexs[i];m_mVexs[i].pFirstEdge = NULL;}char c1,c2;int p1,p2;ENode *node1, *node2;// 初始化"邻接表"的边for (int j = 0; j < elen; j ++){// 读取边的起始顶点和结束顶点p1 = GetVIndex(c1);p2 = GetVIndex(c2);node1 = new ENode();node1->nVindex = p2;node1->nWeight = pEData[j]->nWeight;if (m_mVexs[p1].pFirstEdge == NULL){m_mVexs[p1].pFirstEdge = node1;}else{LinkLast(m_mVexs[p1].pFirstEdge, node1);}node2 = new ENode();node2->nVindex = p1;node2->nWeight = pEData[j]->nWeight;if (m_mVexs[p2].pFirstEdge == NULL){m_mVexs[p2].pFirstEdge = node2;}else{LinkLast(m_mVexs[p2].pFirstEdge, node2);}}}~listUDG(){ENode *pENode = NULL;ENode *pTemp = NULL;for (int i = 0; i < m_nVexNum; i ++){pENode = m_mVexs[i].pFirstEdge;if (pENode != NULL){pTemp = pENode;pENode = pENode->pNext;delete pTemp;}delete pENode;}}void PrintUDG(){ENode *pTempNode = NULL;cout << "邻接⽆向表:" << endl;for (int i = 0; i < m_nVexNum; i ++){cout << "顶点:" << GetVIndex(m_mVexs[i].data)<< "-" << m_mVexs[i].data<< "->"; pTempNode = m_mVexs[i].pFirstEdge;while (pTempNode){cout <<pTempNode->nVindex << "->";pTempNode = pTempNode->pNext;}cout << endl;}}// Prim最⼩⽣成树void Prim(int nStart){int i = 0;int nIndex=0; // prim最⼩树的索引,即prims数组的索引char cPrims[MAX]; // prim最⼩树的结果数组int weights[MAX]; // 顶点间边的权值cPrims[nIndex++] = m_mVexs[nStart].data;// 初始化"顶点的权值数组",// 将每个顶点的权值初始化为"第start个顶点"到"该顶点"的权值。

c语言prim算法

c语言prim算法

c语言prim算法
Prim算法,又称普里姆算法,是一种用于解决最小生成树问题的经典算法。

它以图论为基础,能够在一个具有权重的连通无向图中找到一棵包含所有顶点的树,且树的权重之和最小。

算法的思路相对简单。

假设有一个无向图G,其中顶点集合为V,边集合为E。

算法从一个起始节点开始,逐步扩展生成树的规模,最终得到最小生成树。

1. 初始化:
- 创建一个空的集合T,用于存放最小生成树的边。

- 随机选择一个起始节点s,并将其加入T。

2. 重复以下步骤,直到所有顶点都加入T:
- 在图G中找到一条边e,满足e的一个端点在T中,另一个端点不在T中,并且e的权重最小。

- 将边e加入T,将其另一个端点加入T。

3. 输出最小生成树。

Prim算法的核心在于选择权重最小的边,将其加入生成树。

通过不断扩展生成树的规模,直到包含所有顶点,就能得到最小生成树。

这个算法的时间复杂度为O(V^2),其中V是顶点的数量。

在稠密图中,Prim算法的效率可能较低。

为了提高效率,可以使用最小堆等
数据结构来优化选择最小边的过程,将时间复杂度降到O(ElogV)。

Prim算法在实际应用中有着广泛的用途,如网络设计、电力传输等领域。

它能够帮助我们找到一个具有最小总成本的连接方案,从而提高资源利用效率。

Prim算法是一种解决最小生成树问题的有效算法。

通过选择权重最小的边,逐步扩展生成树的规模,最终得到一个最小总成本的树。

它的应用范围广泛,并且在实际问题中具有重要意义。

希望通过以上的介绍,能够对Prim算法有一个更深入的理解。

最小生成树(prim算法)贪心算法

最小生成树(prim算法)贪心算法

最小生成树算法Prim算法设G=(V,E)是连通带权图,V={1,2,…,n}。

构造G的最小生成树的Prim算法的基本思想是:(1)置S={1}(2)只要S是V的真子集,就作如下的贪心选择选取满足条件i ∈ S,j ∈ V-S,且c[i][j]最小的边,将顶点j添加到S中。

一直到S=V时为止。

(2)选取到的所有边恰好构成G的一棵最小生成树。

源代码://科目:算法实验4//题目:设G=(V,E)是连通带权图,V={1,2,…,n}。

构造G的最小生成树的Prim算法//作者:武叶//语言:C语言//创作时间:2012年4月14日#include"stdio.h"int point[100],key_point[100],tree[100][100]; //定义三个数组用于存放关键点和最小生成树int INT_MAX=0x7fff;void prim(int end,int V); //prim算法函数int main(){int V,E; //定义顶点数V和边数Eint i,j;int start,end,distance; //定义开始顶点start和结束顶点end,以及他们的权值distanceprintf("请输入连通带权图的边数和顶点数:");while(scanf("%d%d",&V,&E)) //开始输入你要求最小生成树的顶点数和边数{printf("\n------------------------------------");for(i=1;i<=V;i++){for(j=1;j<=V;j++)tree[i][j]=INT_MAX;}printf("\n请输入%d条边的起点和终点,以及权值。

\n",E);printf("\n----------------------------------------\n");int x=1; //用x记录输入的边数while(E--){printf("第%d条边的起点:终点:权值:",x);scanf("%d%d%d",&start,&end,&distance); //记录输入的起点、终点、权值tree[start][end]=tree[end][start]=distance;x=x+1;}prim(1,V); //调用prim计算最小生成树printf("\n");}return 0;}void prim(int end,int V){int min; //定义权值最小值minfor(int i=1;i<=V;i++){point[i]=end;key_point[i]=tree[end][i];}key_point[end]=0;for(i=2;i<=V;i++){min= INT_MAX;for(int j=1;j<=V;j++)if(key_point[j]>0 && key_point[j]<min){end=j;min=key_point[j];}printf("起点%d-->终点%d连通\n",point[end],end); //输出最小生成树的连通边key_point[end]=0;for(j=1;j<=V;j++) //继续判断条件if(tree[end][j]<key_point[j])point[j]=end,key_point[j]=tree[end][j];}}运行结果截图:答销网真情提供::文章出处::::/forum.php?mod=viewthread&tid=1533&extra=page%3D1%26filter%3Dtypeid%26typeid%3D3%26typeid%3D3。

普里姆算法实现

普里姆算法实现

普里姆算法实现普里姆算法(Prim算法)是一种用于解决最小生成树问题的贪心算法。

它的基本思想是从一个顶点开始,逐步选择与当前最小生成树连接的最短边,直到所有顶点都被连接为止。

下面是普里姆算法的实现代码:```pythonfrom queue import PriorityQueuedef prim(graph):num_vertices = len(graph)visited = [False] * num_verticesmin_span_tree_cost = 0pq = PriorityQueue()# Start with the first vertexpq.put((0, 0)) # (cost, vertex)while not pq.empty():cost, current_vertex = pq.get()# Skip if vertex is already visitedif visited[current_vertex]:continue# Include current vertex in minimum spanning treevisited[current_vertex] = Truemin_span_tree_cost += cost# Add adjacent vertices to the priority queuefor neighbor in range(num_vertices):if graph[current_vertex][neighbor] != 0 and not visited[neighbor]:pq.put((graph[current_vertex][neighbor], neighbor))return min_span_tree_cost```这段代码使用了优先队列(PriorityQueue)来存储边,每次从队列中取出最小的边。

【报告】最小生成树算法实验报告

【报告】最小生成树算法实验报告

【关键字】报告最小生成树算法➢问题描述设G=(V,E)是一个无向连通带权图,E中每条边(v,w)的权为c(v,w)。

如果G的一个子图G`是一棵包含G的所有顶点的书,则称G`为G的生成树。

生成树上各边权的总和称为该生成树的耗费,在G的所有生成树中,耗费最小的生成树就称为G的最小生成树。

给定一个无向连通带权图,构造一个最小生成树。

➢设计思想利用Prim算法求最小生成树,Prim算法是利用贪心策略设计的算法。

设G=(V,E)是一个连通带权图,V={1,2,…,n}。

构造G的一棵最小生成树的Prim算法的基本思想是:首先置U={1},然后,只要U是V的真子集,就做如下的贪心选择:选取满足条件i∈U,j∈V-U,且使c(i,j)达到最小的边(i,j),并将顶点j添加到U中。

这个过程一致进行到U=V时为止。

在这个过程中选取到的所有边恰好构成G的一棵最小生成树。

➢时间复杂度Prim算法的Pascal语言描述如下:Procedure PRIM(c:array[1..n,1..n] of real);Varlowcost:array[1..n] of real;closest:array[1..n] of integer;i,j,k,min,integer;begin(1)for i:=2 to n do(2)begin{初始化,此时U只含有顶点1}(3)lowcost[i]:=c[1,i];(4)Closest[i]:=1;(5)end;(6)for i:=2 to n do(7)begin {寻找顶点分别在V-U与U中边权最小的边}(8)min:=lowcost[i];(9)j:=i;(10)For k:=2 to n do(11)If lowcost[k]<min then(12)Begin(13)Min:=lowcost[k];(14)j:=k;(15)End;(16)print(j,closest[j]);{输出找到的边}(17)Lowcost[j]:=∞;{将j添加到U}(18)For k:=2 to n do {调整lowcost和closest}(19)if(c[j,k]<lowcost[k])and(lowcost[k]< ∞)then(20)Begin(21)Lowcost[k]:=c[j,k];(22)Closest[k]:=j;(23)End(24)End(25)End;{PRIM}上述过程中第(6)~(24)行的for循环要执行n-1次,每次执行时,第(10)~(15)行和第(18)~(23)行的for循环都要O(n)时间,所以Prim算法所需的计算时间为O(n)。

数据结构最小生成树头歌c语言

数据结构最小生成树头歌c语言

数据结构最小生成树头歌c语言一、前言数据结构中的最小生成树是一种非常重要的算法,它在网络设计、图像处理和社交网络分析等领域有着广泛的应用。

在C语言中,我们可以通过不同的数据结构来实现最小生成树算法,本文将重点介绍如何使用头歌C语言来实现最小生成树算法。

二、数据结构介绍1. 什么是最小生成树在一个连通的无向图中,如果我们要找到一个生成树,并且这个生成树的所有边的权值之和最小,那么这个生成树就是最小生成树。

最小生成树算法有Prim算法和Kruskal算法两种经典的实现方式。

2. 最小生成树的应用最小生成树广泛应用于各种场景中。

比如在计算机网络中,我们可以通过最小生成树算法来构建网络拓扑结构;在社交网络分析中,我们可以基于用户间的关系构建最小生成树,从而发现社区结构;在传感器网络中,最小生成树算法可以用于构建相互连接的传感器网络。

三、 Kruskal算法实现Kruskal算法是一种贪心算法,它的基本思想是:首先将图中的边按照权值的大小进行排序,然后依次加入权值最小的边,并且保证加入的边不会构成回路,直到生成树的边数等于节点数减一为止。

在C语言中,我们可以通过以下步骤来实现Kruskal算法:1. 定义一个结构体来表示边的信息,包括起点、终点和边的权值。

2. 根据边的权值对边进行排序。

3. 使用并查集来判断是否构成回路,如果不构成回路则加入最小生成树中。

4. 重复步骤3直到生成树的边数等于节点数减一。

实际的C语言代码如下所示:```c#include <stdio.h>#include <stdbool.h>#define MAX_EDGE 100#define MAX_VERT 100typedef struct{int from, to;int weight;} Edge;Edge edges[MAX_EDGE];int parent[MAX_VERT];void make_set(int v){parent[v] = v;}int find_set(int v){if (v == parent[v])return v;return parent[v] = find_set(parent[v]); }void union_sets(int a, int b){a = find_set(a);b = find_set(b);if (a != b)parent[b] = a;}int m本人n(){int n, m; // n为节点数,m为边数scanf("dd", n, m);for (int i = 0; i < m; i++)scanf("ddd", edges[i].from, edges[i].to, edges[i].weight);for (int i = 1; i <= n; i++)make_set(i);// 对边按照权值进行排序for (int i = 0; i < m; i++){for (int j = 0; j < m - 1 - i; j++){if (edges[j].weight > edges[j + 1].weight){Edge tmp = edges[j];edges[j] = edges[j + 1];edges[j + 1] = tmp;}}}int cost = 0;for (int i = 0; i < m; i++){if (find_set(edges[i].from) != find_set(edges[i].to)) {printf("d d d\n", edges[i].from, edges[i].to, edges[i].weight);cost += edges[i].weight;union_sets(edges[i].from, edges[i].to);}}printf("Minimum cost = d\n", cost);return 0;}```四、 Prim算法实现Prim算法是另一种最小生成树算法,在C语言中同样可以通过数据结构来实现。

最小生成树三种求解方法的分析与实现

最小生成树三种求解方法的分析与实现

最小生成树三种求解方法的分析与实现作者:李龙霞陈燕于晓倩来源:《电脑知识与技术》2021年第33期摘要:圖作为一种典型的非线性结构,用图来描述问题简明直观。

而最小生成树作为图的重要应用之一,用于解决优化路线,如何使网络通信线路成本最低,电话线路最短等问题。

将此类问题转化为最小生成树问题进行求解。

最小生成树是所有生成树中代价最小的生成树。

它以邻接矩阵的方式存储,采用Prim算法,Kruskal算法和破圈法的方法进行求解。

关键词:图;最小生成树;Prim算法;Kruskal算法;破圈法中图分类号:TP301.6;TP311.12 文献标识码:A文章编号:1009-3044(2021)33-0044-03开放科学(资源服务)标识码(OSID):Analysis and Realization of Three Methods of Solving Minimum Spanning TreeLI Long-xia, CHEN Yan, YU Xiao-qian(School of Maritime Economics and Management, Dalian Maritime University, Dalian 116026, China)Abstract: Graph, as a typical nonlinear structure, is simple and intuitive to describe the problem. As one of the most important applications of graphs, the minimum spanning tree is used to solve the problems of optimizing routes, minimizing the cost of network communication lines and the shortest telephone lines. This kind of problem is transformed into the minimum spanning tree problem to solve. The minimum spanning tree is the spanning tree with the least cost among all spanning trees. It is stored in the form of adjacency matrix and solved by Prim algorithm, Kruskal algorithm and loop breaking method.Key words: Graph; Minimum Spanning Tree; Prim algorithm; Kruskal algorithm; Broken Ring Method1 引言求解最小生成树是解决工程类问题的一种重要手段。

最小生成树算法实验报告_2

最小生成树算法实验报告_2

作业1最小生成树的生成算法1.1算法应用背景在实际生活中, 图的最小花费生成树问题有着广泛的应用。

例如, 用图的顶点代表城市, 顶点与顶点之间的边代表城市之间的道路或通信线路, 用边的权代表道路的长度或通信线路的费用, 则最小花费生成树问题, 就表示为城市之间最短的道路或费用最小的通信线路问题。

其中普里姆算法是使用贪婪法策略设计的典型算法。

1.2算法原理在一给定的无向图G = (V, E) 中, (u, v) 代表连接顶点u 与顶点v 的边(即), 而w(u, v) 代表此边的权重, 若存在T 为E 的子集(即)且为无循环图, 使得的w(T) 最小, 则此T 为G 的最小生成树。

许多应用问题都是一个求无向连通图的最小生成树问题。

例如:要在n个城市之间铺设光缆, 主要目标是要使这n 个城市的任意两个之间都可以通信, 但铺设光缆的费用很高, 且各个城市之间铺设光缆的费用不同;另一个目标是要使铺设光缆的总费用最低。

这就需要找到带权的最小生成树。

1.3算法描述1)最小生成树之普里姆算法描述:令G=(V,E,W), 为简单期间, 令顶点集为V={0,1,2…, n-1}。

假定与顶点i, j相关联的边为ei, j, ei, j的权用c[i][j]表示, T是最小花费生成树的边集。

这个算法维护两个顶点集合S 和N, 开始时: 令T=Ф,S={0},N=V-S。

然后, 进行贪婪选择, 选取i∈S, j∈N, 并且c[i][j]最小的i和j;并使S=S∪S{j},N=N-{j},T=T∪{ei, j}.重复上述步骤, 直到N为空, 或找到n-1条边为止。

此时, T中的边集, 就是所要求取的G中的最小花费生成树。

由此, 可描述普里姆算法的步骤如下:(1)T=Ф, S={0},N=V-S。

(2)如果N为空, 算法结束;否则, 转步骤(3)。

(3)寻找使i∈S, j∈N, 并且c[i][j]最小的i和j。

(4)S=S∪S{j},N=N-{j},T=T∪{ei, j};转步骤(2)。

生成树实验报告总结

生成树实验报告总结

一、实验目的本次实验的主要目的是通过实际操作加深对生成树概念的理解,掌握生成树的构建方法,包括Kruskal算法和Prim算法,并学会使用程序解决实际问题。

二、实验内容1. Kruskal算法Kruskal算法是一种基于边优先的策略来构建最小生成树的算法。

它将所有边按照权值从小到大排序,然后依次选择权值最小的边,同时检查新加入的边是否会构成环。

若不会构成环,则将这条边加入最小生成树中。

2. Prim算法Prim算法是一种基于顶点优先的策略来构建最小生成树的算法。

它从一个顶点开始,逐步扩大最小生成树,直到所有顶点都被包含。

在每次迭代中,算法都会选择一个与已构建的最小生成树连接的最小权值边。

三、实验步骤1. 设计实验环境(1)搭建实验平台:使用C++编程语言,实现Kruskal算法和Prim算法。

(2)设计数据结构:邻接矩阵和邻接表。

2. 编写算法代码(1)Kruskal算法:```cpp// Kruskal算法实现void Kruskal(int n, adjmatrix a) {int i, j, k, u, v;for (i = 1; i <= n; i++) {for (j = i + 1; j <= n; j++) {if (a[i][j] != 0 && a[i][j] != INF) {// 初始化并查集 u = Find(i);v = Find(j);// 合并集合Union(u, v);}}}}```(2)Prim算法:```cpp// Prim算法实现void Prim(int n, adjmatrix a) { int i, j, k, u;int key[MaxNum];int inTree[MaxNum];for (i = 1; i <= n; i++) { key[i] = INF;inTree[i] = false;}key[1] = 0;inTree[1] = true;while (true) {k = -1;for (i = 1; i <= n; i++) {if (!inTree[i] && key[i] < INF) {if (k == -1 || key[i] < key[k]) {k = i;}}}if (k == -1) {break;}inTree[k] = true;for (j = 1; j <= n; j++) {if (!inTree[j] && a[k][j] != INF && a[k][j] < key[j]) { key[j] = a[k][j];}}}}```3. 编译并运行程序(1)使用C++编译器编译代码。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最小生成树Prim算法实现的c ++语言,使用邻接矩阵存储边信息。共三个文件。
第一个
#ifndef __PRIM_H__
#define __PRIM_H__
template <class ElemType, class WeightType>
int MinVertex(const AdjMatrixUndirNetwork<ElemType, WeightType> &net, int *adjVex)
void DeleteEdge(int v1, int v2);//删除顶点为v1和v2的边
WeightType GetWeight(int v1, int v2) const;//返回顶点为v1和v2的边的权值
void SetWeight(int v1, int v2, WeightType w);//设置顶点为v1和v2的边的权值
&& net.GetWeight(v, adjVex[v]) > 0)//存在从v到U的边(v, adjVex[v])
{
w = v;
break;
}
}
for (v++; v < net.GetVexNum(); v++)//查找连接V-U到U的具有最小权值的边<w, adjVex[w]>
if (net.GetTag(v) == UNVISITED && net.GetWeight(v, adjVex[v]) >0 &&
net.GetWeight(v, adjVex[v]) < net.GetWeight(w, adjVex[w]))
w = v;
return w;
}
template <class ElemType, class WeightType>
void MiniSpanTreePrim(const AdjMatrixUndirNetwork<ElemType, WeightType> &net, int u0)
{//初始化标志数组
tag[iPos] = UNVISITED;
}
Matrix = (WeightType **)new WeightType *[vexNum];//生成邻接矩阵
for (iPos = 0; iPos < vexNum; iPos++)
{//生成邻接矩阵的行
Matrix[iPos] = new WeightType[vexNum];
StatusCode GetElem(int v, ElemType &e) const;//求顶点的元素
StatusCode SetElem(int v, const ElemType &e);//设置顶点的元素值
WeightType GetInfinity() const;//返回无穷大
int GetVexNum() const;//返回顶点个数
infinity = infinit;//无穷大
vexNum = vertexNum;//顶点数为vertexNum
edgeNum = 0;//边数为0
elems = new ElemType[vexNum];//生成顶点数据标数组
int iPos;//临时变量
tag = new StatusCode[vexNum];//生成标志数组
AdjMatrixUndirNetwork<ElemType, WeightType> &operator =(const AdjMatrixUndirNetwork<ElemType, WeightType> &copy); //重载赋值运算符
};
template <class ElemType, class WeightType>
{// <v, w>为新的最小边
adjVex[v] = w;
}
}
}
delete []adjVex;//释放存储空间
}
#endif
第二个
#ifndef __ADJ_MATRIX_UNDIR_GRAPH_H__
#define __ADJ_MATRIX_UNDIR_GRAPH_H__
#include "utility.h"//实用程序软件包
//操作结果:返回w,使得边<w, adjVex[w]>为连接V-U到U的具有最小权值的边
{
int w = -1;//初始化最小顶点
int v;//临时顶点
for (v = 0; v < net.GetVexNum(); v++)
{//查找第一个满足条件的V - U中顶点v
if (net.GetTag(v) == UNVISITED//表示v为V - U中的顶点
AdjMatrixUndirNetwork(ElemType es[], int vertexNum = DEFAULT_SIZE,
WeightType infinit = (WeightType)DEFAULT_INFINITY);
//构造顶点数据为es[],顶点个数为vertexNum,infinit表示无穷大,边数为0的无向网
//表示(v, adjVex[v])是v到U具有最小权值边的邻接点
int u, v, w;//表示顶点的临时变量
adjVex = new int[net.GetVexNum()];//分配存储空间
for (v = 0; v < net.GetVexNum(); v++)
{//初始化辅助数组adjVex,并对顶点作标志,此时U = {v0}
AdjMatrixUndirNetwork(int vertexNum = DEFAULT_SIZE,
WeightType infinit = (WeightType)DEFAULT_INFINITY);
//构造顶点个数为vertexNum,infinit表示无穷大,边数为0的无向网
~AdjMatrixUndirNetwork();//析构函数模板
AdjMatrixUndirNetwork<ElemType, WeightType>::AdjMatrixUndirNetwork(ElemType es[], int vertexNum, WeightType infinit)
//操作结果:构造顶点数据为es[],顶点个数为vertexNum,infinit表示无穷大,边数为0的无向网
AdjMatrixUndirNetwork<ElemType, WeightType>::AdjMatrixUndirNetwork(int vertexNum, WeightType infinit)
//操作结果:构造顶点个数为vertexNum,infinit表示无穷大,边数为0的无向网
{
if (vertexNum < 0)throw Error("顶点个数不能为负!");//抛出异常
StatusCode GetTag(int v) const;//返回顶点v的标志
void SetTag(int v, StatusCode val) const;//设置顶点v的标志为val
AdjMatrixUndirNetwork(const AdjMatrixUndirNetwork<ElemType, WeightType> &copy);//复制构造函数模样
for (iPos = 0; iPos < vexNum; iPos++)
{//初始化标志数组
tag[iPos] = UNVISITED;
}
Matrix = (WeightType **)new WeightType *[vexNum];//生成邻接矩阵
//无向网的邻接矩阵类模板
template <class ElemType, class WeightType>
class AdjMatrixUndirNetwork
{
protected:
//邻接矩阵的数据成员:
int vexNum, edgeNum;//顶点个数和边数
WeightType **Matrix;//邻接矩阵
if (v != u0)
tTag(v, UNVISITED);
}
else
{//对于v∈U
net.SetTag(v, VISITED);
adjVex[v] = u0;
}
}
for (u = 1; u < net.GetVexNum(); u++)
{
if (vertexNum < 0)throw Error("顶点个数不能为负!");//抛出异常
infinity = infinit;//无穷大
vexNum = vertexNum;//顶点数为vertexNum
edgeNum = 0;//边数为0
elems = new ElemType[vexNum];//生成顶点数据标数组
{//选择生成树的其余net.GetVexNum() - 1个顶点
w = MinVertex(net, adjVex);
//选择使得边<w, adjVex[w]>为连接V-U到U的具有最小权值的边
if (w == -1)
{//表示U与V-U已无边相连
return;
}
cout << "edge:(" << adjVex[w] << "," << w << ") weight:"
相关文档
最新文档