最小生成树的邻接矩阵实现
来源:互联网 发布:在线ps源码 编辑:程序博客网 时间:2024/06/04 17:53
求上面这个图的最小生成树
参考文档 :http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html
1.prim算法
基本思想:假设G=(V,E)是连通的,TE是G上最小生成树中边的集合。算法从U={u0}(u0∈V)、TE={}开始。重复执行下列操作:
在所有u∈U,v∈V-U的边(u,v)∈E中找一条权值最小的边(u0,v0)并入集合TE中,同时v0并入U,直到V=U为止。
此时,TE中必有n-1条边,T=(V,TE)为G的最小生成树。
Prim算法的核心:始终保持TE中的边集构成一棵生成树。
注意:prim算法适合稠密图,其时间复杂度为O(n^2),其时间复杂度与边得数目无关,而kruskal算法的时间复杂度为O(eloge)跟边的数目有关,适合稀疏图。
2、克鲁斯卡尔(Kruskal)算法(只与边相关)
算法描述:克鲁斯卡尔算法需要对图的边进行访问,所以克鲁斯卡尔算法的时间复杂度只和边又关系,可以证明其时间复杂度为O(eloge)。
算法过程:
1.将图各边按照权值进行排序
2.将图遍历一次,找出权值最小的边,(条件:此次找出的边不能和已加入最小生成树集合的边构成环),若符合条件,则加入最小生成树的集合中。不符合条件则继续遍历图,寻找下一个最小权值的边。
3.递归重复步骤1,直到找出n-1条边为止(设图有n个结点,则最小生成树的边数应为n-1条),算法结束。得到的就是此图的最小生成树。
克鲁斯卡尔(Kruskal)算法因为只与边相关,则适合求稀疏图的最小生成树。而prime算法因为只与顶点有关,所以适合求稠密图的最小生成树。
/* * 普里姆算法和克鲁斯卡尔算法求最小生成树 * 采用邻接矩阵存储 * */#include<stdio.h>#define MAX_VERTEX_NUM 20//图的定义typedef struct {int vertexNum; //图的顶点个数int edgeNum; //图的边的数目char vertex[MAX_VERTEX_NUM]; //图中顶点的内容int arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //图中顶点间的连通性}Graph,*PGraph;//辅助数组元素typedef struct {int from;int to;int weight;int flag;}ArrayNode; //构造无向网void createdGraph(PGraph g){int i,j; g->vertexNum=6;g->edgeNum=10; for(i=0;i<g->vertexNum;i++)g->vertex[i]='A'+i;for(i=0;i<g->vertexNum;i++)for(j=0;j<g->vertexNum;j++) g->arc[i][j]=0;g->arc[0][1]=6;g->arc[0][2]=1;g->arc[0][3]=5;g->arc[1][0]=6;g->arc[1][2]=5;g->arc[1][4]=3;g->arc[2][0]=1;g->arc[2][1]=5;g->arc[2][3]=5;g->arc[2][4]=6;g->arc[2][5]=4;g->arc[3][0]=5;g->arc[3][2]=5;g->arc[3][5]=2;g->arc[4][1]=3;g->arc[4][2]=6;g->arc[4][5]=6;g->arc[5][2]=4;g->arc[5][3]=2;g->arc[5][4]=6;}//初始化最小生成树void initTree(PGraph tree){int i,j; tree->vertexNum=6;tree->edgeNum=5;for(i=0;i<tree->vertexNum;i++)tree->vertex[i]='0';for(i=0;i<tree->vertexNum;i++)for(j=0;j<tree->vertexNum;j++) tree->arc[i][j]=0;}//普里姆算法求最小生成树void prim(PGraph g,PGraph tree){int i,j,k;int index; //指向权值最小的边 ArrayNode edgeArray[MAX_VERTEX_NUM*2]; //辅助数组 int length=0; //数组长度int n=1; //统计数组已加入多少个顶点//初始状态把第一个顶点加入树中tree->vertex[0]='A';printf("%-3c",tree->vertex[0]); i=0; while(1){ //寻找与顶点i相接且这条边的另一个顶点不在树中的边,存入edgeArray数组中for(j=0;j<g->vertexNum;j++){if(g->arc[i][j] > 0){//判断这条边的另一个顶点在不在树中for(k=0;k<tree->vertexNum;k++){if(tree->vertex[k] == g->vertex[j])break;}if(k == tree->vertexNum){ edgeArray[length].from=i; edgeArray[length].to=j; edgeArray[length].weight=g->arc[i][j]; edgeArray[length].flag=0; length++;}}}//从数组中选择权值最小的边index=-1;for(j=0;j<length;j++){if(index == -1 && edgeArray[j].flag == 0)index=j; if(edgeArray[j].flag==0 && edgeArray[j].weight < edgeArray[index].weight)index=j;}//在树中加入一个顶点,且把这条权值最小的边加入树中tree->vertex[edgeArray[index].to]='A'+edgeArray[index].to; edgeArray[index].flag=1;tree->arc[edgeArray[index].from][edgeArray[index].to]=edgeArray[index].weight;tree->arc[edgeArray[index].to][edgeArray[index].from]=edgeArray[index].weight;//当这个顶点加入树中时,与这个顶点相邻的边不可加入树中for(k=0;k<length;k++){if(edgeArray[k].to == edgeArray[index].to)edgeArray[k].flag=1;}i=edgeArray[index].to;printf("%-3c",tree->vertex[i]);n++;//当有g->vertexNum个顶点时,最小生成树构造完成if(n==g->vertexNum)break;}}//判断两个顶点是否连通(广度优先搜索)int connected(PGraph tree,int from,int to){int i,j,k;int vertex[MAX_VERTEX_NUM];//看成队列int front,rear;if(from==to)return 1;front=rear=0;//把第一个顶点存入数组vertex[rear++]=from;//遍历treewhile(front<=rear){i=vertex[front]; for(j=0;j<tree->vertexNum;j++)if(tree->arc[i][j]>0){if(j==to)return 1;//判断此顶点是否在队列中for(k=0;k<rear;k++)if(vertex[k] == j)break;if(k==rear) vertex[rear++]=j;}front++;}return 0;}//克鲁斯卡尔算法求最小生成树void kruskal(PGraph g,PGraph tree){ ArrayNode edgeArray[MAX_VERTEX_NUM]; //辅助数组 int length=0;int i,j,k,index,n;//顶点先加入树中for(i=0;i<tree->vertexNum;i++)tree->vertex[i]=i+'A';//1.把所有的边有序(从小到大)的插入edgeArray数组中for(i=0;i<g->vertexNum;i++)for(j=0;j<g->vertexNum;j++){if(i<j && g->arc[i][j]>0){//寻找插入的位置indexfor(k=0;k<length;k++){ if(edgeArray[k].weight > g->arc[i][j])break;}index=k; //移位for(k=length;k>index;k--) edgeArray[k]=edgeArray[k-1];//插入length++;edgeArray[index].flag=0;edgeArray[index].from=i;edgeArray[index].to=j;edgeArray[index].weight=g->arc[i][j];}}//2.从小到大取出n-1条边构造最小生成树n=0;while(n < g->vertexNum-1){//从小到大取一条符合要求的边for(k=0;k<length;k++)if(edgeArray[k].flag==0 && connected(tree,edgeArray[k].from,edgeArray[k].to)==0){break;}//把这条边加入树中tree->arc[edgeArray[k].from][edgeArray[k].to]=edgeArray[k].weight;tree->arc[edgeArray[k].to][edgeArray[k].from]=edgeArray[k].weight; edgeArray[k].flag=1;printf("%-3d",edgeArray[k].weight);n++;}}void main(){Graph graph;Graph tree;createdGraph(&graph);initTree(&tree);printf("普里姆算法树中顶点加入的顺序:\n");prim(&graph,&tree);printf("\n");initTree(&tree);printf("克鲁斯卡尔算法树中边加入的顺序:\n");kruskal(&graph,&tree);printf("\n");}
- 最小生成树的邻接矩阵实现
- 邻接矩阵实现图+深度/广度优先遍历+最小生成树
- 邻接矩阵实现图+深度/广度优先遍历+最小生成树
- 最小生成树 prim算法实现(利用图的邻接矩阵来存放图)
- 数据结构——邻接矩阵的最小生成树Kruskal算法
- 数据结构——邻接矩阵的最小生成树Prim算法
- 邻接矩阵 最小生成树 普里姆算法
- 最小生成树Prim算法(邻接矩阵)
- 基于邻接矩阵存储的无向网图的创建,最小生成树算法实现完整代码
- Java实现图:邻接矩阵表示、深度优先搜索、广度优先搜索、无向图的最小生成树
- 图的遍历和生成树求解实现|图遍历,生成树,实现,邻接矩阵,邻接表,深度广度遍历,最小生成树
- 图邻接矩阵存储 最小生成树 prim普里姆算法 C语言实现
- Prim算法(邻接矩阵无相图)求最小生成树 C 实现 ~
- 基于邻接矩阵存储的图的最小生成树的Prime算法
- 基于邻接矩阵存储的图的最小生成树的Prime算法
- 数据结构——邻接矩阵的最小生成Prim算法
- 邻接矩阵基础的Prime算法(最小生成矩阵)
- 数据结构-图-Java实现:有向图 图存储(邻接矩阵),最小生成树,广度深度遍历,图的连通性,最短路径
- ios应用在后台运行时间讨论
- 关于.bashrc文件的几点思考
- VS快捷键大全
- bzoj3295(线段树套平衡树(treap))
- PagerTabStrip和PagerTitleStrip
- 最小生成树的邻接矩阵实现
- CentOS赋予一个普通用户root权限
- Yii Framework 开发教程(4) Hangman 猜单词游戏实例
- 详细解析Java中抽象类和接口的区别
- 部署一个已上线的项目报找不到类的错误,修改工程CLASS生成的路径
- ASP.NET(C#)中将TextBox控件的Readonly属性设置为True时后台直接取值取不到的解决方案
- Java Web开发常用Jar包
- 通过ipsw控制固定端口的网速
- 错误22022 SQLServerAgent当前未运行的解决方法