算法分析与设计作业一之Prim算法和Kruskal算法的图解及代码实现
Prim算法:
一、问题描述:
在带权连通图中V是包含所有顶点的集合,U是已经在最小生成树中的节点。开始时,从图中任意某一顶点v开始,此时集合U={v}(以v到其他顶点的所有边为侯选边);在所有u∈U,w∈V-U的边(u,w)∈E中找到一条权值最小的边,将(u,w)这条边加入到已找到边的集合,并且将点w加入到集合U中,重复上一操作,当U=V时,就找到了这颗最小生成树。
二、算法核心步骤(伪代码)及图解:
(1) 定义min存取最小权值,lowcost[]、adjvex[]分别存权值和顶点下标;
(2) For循环遍历所有与v0相邻的边,并初始化全部顶点为v0下标;
(3) 初始化最小权值为最大的不可能值,遍历全部顶点,找到最小权值;
(4) 打印当前顶点边中权值最小的边,邻接矩阵逐个遍历全部顶点,将较小的权值存入lowcost[],将下标为k的顶点存入adjvex中。
三、代码实现:
#include <stdio.h> #define MAXVEX 10 #define TRUE 1 #define FALSE 0 #define Maxweight 65535//此处是权值极最大值 #define LENGTH(a) (sizeof(a) / sizeof(a[0])) typedef char VertexType; typedef struct { VertexType vexs[MAXVEX]; //存储顶点信息 int arc[MAXVEX][MAXVEX]; //邻接矩阵 int numVertexes, numEdges; //边数和点数 }MGraph; void createMGraph(MGraph *G) // 创建图 { int i, j; printf("请输入边数和顶点数:"); scanf("%d %d",&G->numEdges,&G->numVertexes); //G->numEdges=10; //G->numVertexes=6; for (i = 0; i < G->numVertexes; i++) // 初始化图 { for ( j = 0; j < G->numVertexes; j++) { if (i==j) G->arc[i][j]=0; else G->arc[i][j] = G->arc[j][i] = Maxweight; } } G->arc[0][1]=6; G->arc[0][2]=1; G->arc[0][3]=5; G->arc[1][2]=5; G->arc[1][4]=3; G->arc[2][3]=7; G->arc[2][4]=5; G->arc[2][5]=4; G->arc[3][5]=2; G->arc[4][5]=6; for(i = 0; i < G->numVertexes; i++) { for(j = i; j < G->numVertexes; j++)//注意 这里j的起点是从i开始的 { G->arc[j][i] =G->arc[i][j];//因为是无向图 所以顶点具有对称性 } } } //Prim 算法生成最小生成树 void Prim(MGraph G) { int min, i, j, k; int lowcost[MAXVEX]; // 权值 int adjvex[MAXVEX]; // 顶点的下标 lowcost[0] = 0; //v0权值为0 adjvex[0] = 0; // v0第一个加入 for(i = 1; i < G.numVertexes; i++) { lowcost[i] = G.arc[0][i]; // 遍历所有与v0相邻的边 adjvex[i] = 0; // 初始化全部先为 v0 的下标 } for(i = 1; i < G.numVertexes; i++) { min = Maxweight; // 初始化最小权值为最大的不可能值 j = 1; k = 0; while(j < G.numVertexes) // 遍历全部顶点 { if(lowcost[j] != 0 && lowcost[j] < min) { min = lowcost[j]; k = j; } j++; } lowcost[k] = 0; // 将当前顶点的权值设置为0 printf("(%d, %d)", adjvex[k], k); // 打印当前顶点边中权值最小的边 //邻接矩阵k行逐个遍历全部顶点 for(j = 1; j < G.numVertexes; j++) { if(lowcost[j] != 0 && G.arc[k][j] < lowcost[j]) { lowcost[j] = G.arc[k][j]; // 将较小的权值存入 lowcost 相应位置 adjvex[j] = k; // 将下标为 k 的顶点存入 adjvex } } } } int main() { MGraph G; createMGraph(&G); Prim(G); return 0; }
四、Prim算法时间复杂度分析:
顶点数为v,边数为e,邻接矩阵复杂度为:O(v^2) 邻接表:O(elog2 v);
Kruskal算法:
一、问题描述:
在带权连通图中V是包含所有顶点的集合,U是已经在最小生成树中的节点。开始时,对图中所有权值进行排序,找到最小的权值所在边,将这条边所连接的两端点放入集合U,重复上一操作,当找到n-1条边时,就找到了这颗最小生成树。
二、算法核心步骤(伪代码)及图解:
(1)新建图G,G中拥有原图中相同的节点,但没有边;
(2)将原图中所有的边按权值从小到大排序;
(3)从权值最小的边开始,如果这条边连接的两个节点于图G中不在同一个连通分量中,则添加这条边到图G中;
(4)重复3,直至图G中所有的节点都在同一个连通分量中。
三、代码实现:
#include <stdio.h> #define MAXVEX 10 #define TRUE 1 #define FALSE 0 typedef struct{ int vertex1; //存储边的起始顶点 int vertex2; //存储边的终止顶点 int weight; //权值 }Edge; int kruskal(Edge Edges[],int n,int e) { int i,j,v1,v2,a1,a2,k; int a[n+1]; for(i=1;i<=n;i++) a[i]=i; k=1; j=0; //下标初值为0 while(k<e) //生成的边数小于e时继续循环 { v1=Edges[j].vertex1; v2=Edges[j].vertex2; //取一条边的两个邻接点 a1=a[v1]; a2=a[v2]; if(a1!=a2) //防止出现闭合回路 { printf("(%d,%d)\n",v1,v2); k++; //生成边数增加 if(k>=n) break; for(i=1;i<=n;i++) if (a[i]==a2) a[i]=a1; } j++; } } int sort(Edge arr[],int low,int high) { int key; Edge min; min=arr[low]; key=arr[low].weight; while(low<high) { while(low<high && arr[high].weight>=key) high--; if(low<high) arr[low++]=arr[high]; while(low<high && arr[low].weight<=key) low++; if(low<high) arr[high--]=arr[low]; } arr[low]=min; return low; } void quick_sort(Edge arr[],int start,int end) { int pos; if(start<end) { pos=sort(arr,start,end); quick_sort(arr,start,pos-1); quick_sort(arr,pos+1,end); } } int main() { Edge Edges[MAXVEX]; int numEdges,numVertexes; printf("输入顶数和边数:\n"); scanf("%d%d",&numVertexes,&numEdges); for(int i=0;i<numEdges;i++) { scanf("%d%d%d",&Edges[i].vertex1,&Edges[i].vertex2,&Edges[i].weight); } quick_sort(Edges,0,numEdges-1); kruskal(Edges,numVertexes,numEdges); }
四、Kruskal算法时间复杂度分析:
平均时间复杂度为O(|E|log|E|),其中E和V分别是图的边集和点集。
- 点赞
- 收藏
- 分享
- 文章举报
- 算法分析与设计实践 - 作业1 - 分别采用Prim算法和Kruskal算法构建最小生成树
- 算法分析与设计作业1:Prim算法与Kruskal算法构造最小生成树
- 算法设计(动态规划):机器人路径规划(JAVA代码实现及题目分析)
- 算法分析与设计 - 作业1 - Prim算法求最小生成树
- 【算法分析与设计】最小生成树Kruskal算法和Prim算法
- 算法设计(动态规划):新水果取名(JAVA代码实现及题目分析)
- 算法设计(动态规划):拦截导弹问题(JAVA代码实现及题目分析)
- 结对作业——电梯调度算法的实现与测试之需求分析与算法设计
- 算法分析与设计-作业1-Prim算法生成最小生成树
- web前端学习笔记-瀑布流的算法分析与代码实现
- 应用框架的设计与实现——.NET平台(9 消息队列服务代码分析)
- 算法设计步步高:1.入手从最容易想到的分析开始写代码 2.分析补缺 3.补漏及完善 4.稍事优化
- 算法与设计分析作业3(贪心)
- 无监督学习之K-均值算法分析与MATLAB代码实现
- 主成分分析(pca)算法的实现步骤及代码
- 算法设计与分析--霍夫曼树编码(C++实现)
- 【字符串处理算法】字符串包含的算法设计及C代码实现
- 【JS 设计模式 】用组合模式来实现树形导航--代码结构思路分析(一)
- 第七篇:Logistic回归分类算法原理分析与代码实现
- 【算法分析与设计】快速求幂算法的分析及java实现