普里姆算法求最小生成树精编版
普里姆算法构造最小生成树的过程

普里姆算法构造最小生成树的过程介绍如下:
1.从任意一个点开始,将该点加入已选点集中。
2.对于已选点集中的每一个点,找到与其相连的所有边中权值最
小的边,并记录该边的另一个端点。
3.在所有记录的点中选择一个与已选点集相连的权值最小的点,
并将该点加入已选点集中,同时将该点与已选点集中的某个点(如与其相连的权值最小的点)之间的边加入最小生成树中。
4.重复步骤2和步骤3,直到已选点集包含所有点为止。
最终得到的最小生成树是所有可能的生成树中权值最小的一棵。
该算法的时间复杂度为O(ElogV),其中E为边数,V为点数。
求出下图的最小生成树

求出下图的最小生成树解: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算法求最小生成树

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算法)最⼩⽣成树的性质: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数组记录各点的连通分量),则将其添加到最⼩⽣成树中。
普里姆算法(Prim)求最小生成树C程序

程序测试用例如下:程序运行过程截图:源程序清单如下:#include <stdio.h>#define n 6#define MaxNum 10000 /*定义一个最大整数*/2 6 4 43 5 5 1 5 6 1 2 43 5 6/*定义邻接矩阵类型*/typedef int adjmatrix[n+1][n+1]; /*0号单元没用*/typedef struct{int fromvex,tovex;int weight;}Edge;typedef Edge *EdgeNode;int arcnum; /*边的个数*//*建立图的邻接矩阵*/void CreatMatrix(adjmatrix GA){int i,j,k,e;printf("图中有%d个顶点\n",n);for(i=1;i<=n;i++){for(j=1;j<=n;j++){if(i==j){GA[i][j]=0; /*对角线的值置为0*/}else{GA[i][j]=MaxNum; /*其它位置的值置初始化为一个最大整数*/ }}}printf("请输入边的个数:");scanf("%d",&arcnum);printf("请输入边的信息,按照起点,终点,权值的形式输入:\n");for(k=1;k<=arcnum;k++){scanf("%d,%d,%d",&i,&j,&e); /*读入边的信息*/GA[i][j]=e;GA[j][i]=e;}}/*初始化图的边集数组*/void InitEdge(EdgeNode GE,int m){int i;for(i=1;i<=m;i++){GE[i].weight=0;}}/*根据图的邻接矩阵生成图的边集数组*/void GetEdgeSet(adjmatrix GA,EdgeNode GE){ int i,j,k=1;for(i=1;i<=n;i++){for(j=i+1;j<=n;j++){if(GA[i][j]!=0&&GA[i][j]!=MaxNum){GE[k].fromvex=i;GE[k].tovex=j;GE[k].weight=GA[i][j];k++;}}}}/*按升序排列图的边集数组*/void SortEdge(EdgeNode GE,int m){int i,j,k;Edge temp;for(i=1;i<m;i++){k=i;for(j=i+1;j<=m;j++){if(GE[k].weight>GE[j].weight){k=j;}}if(k!=i){temp=GE[i];GE[i]=GE[k];GE[k]=temp;}}}/*利用普里姆算法从初始点v出发求邻接矩阵表示的图的最小生成树*/void Prim(adjmatrix GA,EdgeNode T){int i,j,k,min,u,m,w;Edge temp;/*给T赋初值,对应为v1依次到其余各顶点的边*/k=1;for(i=1;i<=n;i++){if(i!=1){T[k].fromvex=1;T[k].tovex=i;T[k].weight=GA[1][i];k++;}}/*进行n-1次循环,每次求出最小生成树中的第k条边*/for(k=1;k<n;k++){min=MaxNum;m=k;for(j=k;j<n;j++){if(T[j].weight<min){min=T[j].weight;m=j;}}/*把最短边对调到k-1下标位置*/temp=T[k];T[k]=T[m];T[m]=temp;/*把新加入最小生成树T中的顶点序号赋给j*/j=T[k].tovex;/*修改有关边,使T中到T外的每一个顶点保持一条到目前为止最短的边*/for(i=k+1;i<n;i++){u=T[i].tovex;w=GA[j][u];if(w<T[i].weight){T[i].weight=w;T[i].fromvex=j;}}}}/*输出边集数组的每条边*/void OutEdge(EdgeNode GE,int e){int i;printf("按照起点,终点,权值的形式输出的最小生成树为:\n");for(i=1;i<=e;i++){printf("%d,%d,%d\n",GE[i].fromvex,GE[i].tovex,GE[i].weight);}}void main(){adjmatrix GA;Edge GE[n*(n-1)/2],T[n];CreatMatrix(GA);InitEdge(GE,arcnum);GetEdgeSet(GA,GE);SortEdge(GE,arcnum);Prim(GA,T);printf("\n");OutEdge(T,n-1);}。
数据结构第7章-答案

一、单选题C01、在一个图中,所有顶点的度数之和等于图的边数的倍。
A)1/2 B)1 C)2 D)4B02、在一个有向图中,所有顶点的入度之和等于所有顶点的出度之和的倍。
A)1/2 B)1 C)2 D)4B03、有8个结点的无向图最多有条边。
A)14 B)28 C)56 D)112C04、有8个结点的无向连通图最少有条边。
A)5 B)6 C)7 D)8C05、有8个结点的有向完全图有条边。
A)14 B)28 C)56 D)112B06、用邻接表表示图进行广度优先遍历时,通常是采用来实现算法的。
A)栈 B)队列 C)树 D)图A07、用邻接表表示图进行深度优先遍历时,通常是采用来实现算法的。
A)栈 B)队列 C)树 D)图A08、一个含n个顶点和e条弧的有向图以邻接矩阵表示法为存储结构,则计算该有向图中某个顶点出度的时间复杂度为。
A)O(n) B)O(e) C)O(n+e) D)O(n2)C09、已知图的邻接矩阵,根据算法思想,则从顶点0出发按深度优先遍历的结点序列是。
A)0 2 4 3 1 5 6 B)0 1 3 6 5 4 2 C)0 1 3 4 2 5 6 D)0 3 6 1 5 4 2B10、已知图的邻接矩阵同上题,根据算法,则从顶点0出发,按广度优先遍历的结点序列是。
A)0 2 4 3 6 5 1 B)0 1 2 3 4 6 5 C)0 4 2 3 1 5 6 D)0 1 3 4 2 5 6D11、已知图的邻接表如下所示,根据算法,则从顶点0出发按深度优先遍历的结点序列是。
A)0 1 3 2 B)0 2 3 1 C)0 3 2 1 D)0 1 2 3A12、已知图的邻接表如下所示,根据算法,则从顶点0出发按广度优先遍历的结点序列是。
A)0 3 2 1 B)0 1 2 3 C)0 1 3 2 D)0 3 1 2A13、图的深度优先遍历类似于二叉树的。
A)先序遍历 B)中序遍历 C)后序遍历 D)层次遍历D14、图的广度优先遍历类似于二叉树的。
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 个顶点、n-1 条边。
构造最小生成树的准则 必须使用且仅使用该网络中的n-1 条边 来联结网络中的 n 个顶点; 不能使用产生回路的边; 各边上的权值的总和达到最小。
采用邻接矩阵作为图的存储表示。
28
01
01
01
10 14 16 10
10
5 6 25 6 25 6 2
25 24 18 12
25
4 22 3
43
43
原图
(a)
(b)
01
01
01
10
10
10 14 16
5 6 25 6 25 6 2
25
4 22 3
(c)
25
12 25
12
4 22 3
4 22 3
(d)
普里姆(Pபைடு நூலகம்im)算法
普里姆算法的基本思想: 从连通网络 N = { V, E }中的某一顶点 u0 出 发, 选择与它关联的具有最小权值的边 ( u0, v ), 将其顶点加入到生成树顶点集合U中。 以后每一步从一个顶点在 U 中,而另一个 顶点不在 U 中的各条边中选择权值最小的 边(u, v), 把它的顶点加入到集合 U 中。如 此继续下去, 直到网络中的所有顶点都加入 到生成树顶点集合 U 中为止。
(e) (f)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
沈阳航空航天大学课程设计报告课程设计名称:数据结构课程设计课程设计题目:Prim算法求最小生成树院(系):计算机学院专业:计算机科学与技术(物联网方向)班级:学号:姓名:指导教师:学术诚信声明本人声明:所呈交的报告(含电子版及数据文件)是我个人在导师指导下独立进行设计工作及取得的研究结果。
尽我所知,除了文中特别加以标注或致谢中所罗列的内容以外,报告中不包含其他人己经发表或撰写过的研究结果,也不包含其它教育机构使用过的材料。
与我一同工作的同学对本研究所做的任何贡献均己在报告中做了明确的说明并表示了谢意。
报告资料及实验数据若有不实之处,本人愿意接受本教学环节“不及格”和“重修或重做”的评分结论并承担相关一切后果。
本人签名: 日期:2015 年 1 月15 日沈阳航空航天大学课程设计任务书计算机科学与技术课程设计名称数据结构课程设计专业(物联网方向)学生姓名班级学号题目名称Prim算法生成最小生成树起止日期2015 年 1 月 5 日起至2015 年 1 月16 日止课设内容和要求:在n个城市之间建立网络,只需保证连通即可,求最经济的架设方法,利用Prim算法输出n个城市之间网络图,输出n个节点的最小生成树。
其中,n个城市表示n个节点,两个城市间如果有路则用边连接,生成一个n个节点的边权树,要求键盘输入。
参考资料:算法与数据结构,严蔚敏、吴伟民,清华大学出版社,2006C程序设计,谭浩强,清华大学出版社,2010教研室审核意见:教研室主任签字:指导教师(签名)年月日学生(签名)2015 年 1 月15 日目录学术诚信声明 .............................................................................................................. - 1 -一课程设计目的和要求.......................................................................................... - 4 -1.1课程设计目的 .. (4)1.2课程设计的要求 (4)二实验原理分析 ........................................................................................................ - 5 -2.1最小生成树的定义 (5)2.2P RIM算法的基本思想 (5)三概要分析和设计 .................................................................................................... - 8 -3.1概要分析 . (8)3.2概要设计 (9)四测试结果 ............................................................................................................ - 14 -4.1实验一 . (14)4.2实验二 (14)4.3实验三 (15)参考文献 .................................................................................................................... - 16 -附录(关键部分程序清单).............................................................................. - 17 -一课程设计目的和要求1.1 课程设计目的(一)根据算法设计需要,掌握连通网的数据表示方法;(二)掌握最小生成树的Prim算法;(三)学习独立撰写报告文档。
1.2 课程设计的要求在n个城市之间建立网络,只需保证连通即可,求最经济的架设方法,利用Prim算法输出n个城市之间网络图,输出n个节点的最小生成树。
其中,n个城市表示n个节点,两个城市间如果有路则用边连接,生成一个n个节点的边权树,要求键盘输入。
二实验原理分析2.1 最小生成树的定义一个有n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有n 个结点,并且有保持图连通的最少的边。
最小生成树可以用kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。
(1). 最小生成树的概述在一给定的无向图G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即),而 w(u, v) 代表此边的权重,若存在 T 为 E 的子集(即)且为无循环图,使得 w(T) 最小,则此 T 为 G 的最小生成树。
最小生成树其实是最小权重生成树的简称。
(2). 最小生成树的分析构造最小生成树可以用多种算法。
其中多数算法利用了最小生成树的下面一种简称为MST的性质:假设N=(V,{E})是一个连通网,U 是顶点集V的一个非空子集。
若(u,v)是一条具有最小权值(代价)的边,其中u∈U,v∈V-U,则必存在一棵包含边(u.v)的最小生成树。
2.2 Prim算法的基本思想假设G =(V,E)是一个具有n个顶点的连通网,T=(U,TE)是G的最小生成树,其中U是T的顶点集,TE是T的边集,U和TE的初值均为空集。
算法开始时,首先从V中任取一个顶点(假定取V0),将它并入U中,此时U={V0},然后只要U是V的真子集,就从那些其一个端点已在T中,另一个端点仍在T外的所有边中,找一条最短(即权值最小)边,假定为(i,j),其中Vi∈U,Vj∈(V-U),并把该边(i,j)和顶点j分别并入T的边集TE和顶点集U,如此进行下去,每次往生成树里并入一个顶点和一条边,直到n-1次后就把所有n个顶点都并入到生成树T的顶点集中,此时U=V,TE中含有n-1条边,T就是最后得到的最小生成树。
可以看出,在普利姆算法中,是采用逐步增加U中的顶点,常称为“加点法”。
为了实现这个算法在本设计中需要设置一个辅助数组closedge[ ],以记录从U到V-U具有最小代价的边。
当辅助数组中存在两个或两个以上的最小代价的边时,此时最小生成树的形态就不唯一,此时可以在程序中采用递归的算法思想求出每个最小生成树。
(1). 在prim算法中要解决两个问题1)在无向网中,当从一个顶点到其他顶点时,若其边上的权值相等,则可能从某一起点出发时,会得到不同的生成树,但最小生成树的权值必定相等,此时我们应该如何把所有的最小生成树求解出来;2)每次如何从生成树T中到T外的所有边中,找出一条权值最小的边。
例如,在第k次(1≤k≤n-1)前,生成树T中已有k个顶点和k-1条边,此时T中到T外的所有边数为k(n-k),当然它也包括两顶点间没有直接边相连,其权值被看作常量的边在内,从如此多的边中找出最短的边,其时间复杂度0(k (n-k)),是很费时间的,是否有好的方法能够降低查找最短边的时间复杂度。
(2). 上述问题的解决方法针对1)中出现的问题,可以通过算法来实现,详情请看Prim算法的概述;针对2)中出现的问题,通过对Prim算法的分析,可以使查找最短边的时间复杂度降低到O(n-k)。
具体方法是假定在进行第k次前已经保留着从T中到T外的每一顶点(共n-k个顶点)的各一条最短边,进行第k次时,首先从这n-k条最短边中,找出一条最最短的边,它就是从T中到T外的所有边中的最短边,假设为(i,j),此步需进行n-k次比较;然后把边(i,j)和顶点j分别并入T中的边集TE和顶点集U中,此时T外只有n-(k+1)个顶点,对于其中的每个顶点t,若(j,t)边上的权值小于已保留的从原T中到顶点t的最短边的权值,则用(j,t)修改之,使从T中到T外顶点t的最短边为(j,t),否则原有最短边保持不变,这样,就把第k次后从T中到T外每一顶点t的各一条最短边都保留下来了,为进行第k+1次运算做好了准备,此步需进行n-k-1次比较。
所以,利用此方法求第k次的最短边共需比较2(n-k)-1次,即时间复杂度为O(n-k)。
三概要分析和设计3.1 概要分析通过对上述算法的分析,将从以下三方面来进行分析:(1). 输入数据的类型在本次设计中,是对无向图进行操作,网中的顶点数,边数,顶点的编号及每条边的权值都是通过键盘输入的,他们的数据类型均为整型,其中,权值的范围为0~32768(即“∞”);(2). 输出数据的类型当用户将无向图创建成功以后,就可以通过键盘任意输入一个起点值将其对应的最小生成树的生成路径及其权值显示出来;(3). 测试数据本次设计中是通过用Prim算法求最小生成树,分别用以下三组数据进行测试:(一)假设在创建无向图时,只输入一个顶点,如图1所示,验证运行结果;A图1.单一节点的无向图(二)假设创建的无向图如图2所示,验证运行结果;图2.网中存在权值相等的边(三)假设创建的无向图如图3所示,验证结果;图3,网中的权值各不相等3.2 概要设计在本次设计中,网的定义为G=(V,E),V表示非空顶点集,E表示边集,其存储结构这里采用邻接矩阵的方式来存储。
1 数据类型的定义在本设计中所涉及到的数据类型定义如下:(1). 符号常量的定义算法中涉及到两个符号常量,定义如下:#define MAX 20 功能:用于表示网中最多顶点个数;#define INFINIT 32768 功能:用于表示权的最大值,即∞。
(2). 结构体的定义整个算法中涉及的结构体定义如下:✓定义结构体ArcNode功能:用于存放边的权值typedef struct{int adj;//权值}ArcNode;✓定义结构体AdjMatrix功能:用于表示网的结构及存储方式。
typedef struct{int vexs[MAX];//vexs表示顶点向量int vexnum,arcnum;//分别表示图的顶点数和弧数ArcNode arcs[MAX][MAX];//邻接矩阵}AdjMatrix✓定义结构体Node功能:用于表示求最小生成树时用到的辅助数组。
typedef struct{int adjvex;//存放顶点编号int lowcost;//存放顶点权值}Node;✓外部变量的定义算法中涉及到两个外部变量,定义如下:Node close[MAX]功能:存放每个顶点所连接的边所对应的权值;int flag=0功能:标志变量,当创建网时,输入的顶点个数<=1时,直接输出“不存在最小生成树”程序不在往后执行,否则继续往下执行。