这个是以前所学,现在总结成博文一篇。
对于图论中的求解最小支撑树问题和最短路径问题都有比较经典的算法,比如最小支撑树可以采用“破圈法”(kruskal算法),求解最短路径可以用“Dijkstra算法”。这里笔者将回顾下求解最小支撑树的Prim算法和最短路径算法。
1、Prim算法求解最小支撑树
例1:用Prim算法求解图1的一个最小支撑树。
图1:例图
首先,给出Prim算法:
实现的C语言代码如下:
#include<stdio.h> int matrix[100][100]; int E[100]={0},tree[100][100]={0}; int n,i,j; void inputmatrix() { printf("请输入邻接矩阵的阶数:\n"); scanf("%d",&n); printf("请输入邻接矩阵:\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) scanf("%d",&matrix[i][j]); } } void caculate(int n,int a[100][100]) { int k=n-1,t=0,t1,t2,min,j,m=1,flag=1;/*k,k1作为循环的次数,flag标记是否有支撑树*/ E[0]=1; /*先放入一个点*/ tree[0][0]=a[0][0]; while(k--) { min=100000; for(j=0;j<n;j++) { for(i=0;i<n;i++) if(E[i]==1&&E[j]==0&&min>a[i][j]&&a[i][j]!=0) /*寻找符合条件的数*/ { t1=j; t2=i; min=a[i][j]; } } E[t1]=1; /*标记为1,代表已经用过*/ tree[t2][t1]=a[t2][t1]; /*记录值*/ tree[t1][t2]=a[t1][t2]; /*记录值*/ m++; } for(i=0;i<n;i++) { if(E[i]==0) { printf("没有支撑树\n"); flag=0; break; } } if(flag==1) /*证明存在支撑树*/ { printf("输出对应的最小支撑树所对应的矩阵:\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) printf("%d ",tree[i][j]); printf("\n"); } } } main() { inputmatrix(); caculate(n,matrix); system("pause"); }
2、改进的Prim算法求解最短路径
例2:利用改进的Prim算法求解图2的最短路径问题。
图2:例图
首先给出该算法的描述。
下面是该算法的C语言实现。
#include<stdio.h> int matrix[100][100]; int E[100]={0},distance[100]={0}; int path[100][100] = {0};//初试为空,记录path int n,i,j,ini;//ini为初始下标 char temp[100]; void inputmatrix() { printf("请输入邻接矩阵的阶数:\n"); scanf("%d",&n); printf("请输入有向图的邻接矩阵(输入0代表无穷大):\n"); for(i=0;i<n;i++) { for(j=0;j<n;j++) scanf("%d",&matrix[i][j]); } printf("请输入需计算的起始点下标:\n"); scanf("%d",&ini); E[ini-1]=1; path[ini-1][0]=ini; } void caculate(int n,int a[100][100]) { int k=n-1,t=0,t1,t2,min,j,m=1,w,flag=0;/*k,k1作为循环的次数,flag=1意味着可以继续循环,flag=0,跳出*/ while(k--) { min=100000; flag=0;// 初始化 for(j=0;j<n;j++) { for(i=0;i<n;i++) if(E[i]==1&&E[j]==0&&min>(a[i][j]+distance[i])&&a[i][j]>0) /*寻找符合条件的数*/ { flag=1;// 标记为1,找到!继续循环 t1=j; t2=i; min=a[i][j]+distance[i]; } } if(flag==0) break;//跳出 distance[t1]=min; E[t1]=1; /*标记为1,代表已经用过*/ for(j=0;j<n;j++)//把t2的值加给t1,并且最后加上t1该点 { if(path[t2][j]!=0) { path[t1][j]=path[t2][j]; } else { path[t1][j]=t1+1; break; } } m++; } printf("\n\n----下面为反圈法(prim法)计算结果----\n\n",ini,i+1,distance[i]); for(i=0;i<n;i++) { if(E[i]==1) { printf("点%d到点%d的最小距离:%d\n",ini,i+1,distance[i]); printf("其最短路径:"); for(j=0;j<n;j++) { if(path[i][j]!=0) { printf("v%d ",path[i][j]); } else break; } printf("\n"); } else printf("点%d到点%d没有路可通!\n\n",ini,i+1); } } main() { inputmatrix(); caculate(n,matrix); system("pause"); }
笔者水平有限,难免有不足,请批评指正!