本篇意在总结有关图的一些基本算法
包括有图的最小生成树(Prim,Kruscal),最短路径(Dijkstra,Floyd),拓扑排序等算法
本篇图的数据结构为矩阵表示法
// project1.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include<string.h> #include<assert.h> #include<stdio.h> #include<stdlib.h> #define MAX 100 #define INFINITY (unsigned int)-1 //邻接矩阵表示法 struct MGraph{ char vexs[MAX];//顶点 unsigned int edges[MAX][MAX];//边 int vexnum,edgenum; int kind; //图的类型,0无向图,1有向图,2带权无向图,3带权有向图 MGraph(int vn=0,int en=0,int kind=0):vexnum(vn),edgenum(en),kind(kind){ } }; //通过输入创建图矩阵 void createMGraphFromStdin(MGraph *g){ assert(g); printf("input vexnum, edgenum, and graph kind: "); assert(scanf("%d,%d,%d",&g->vexnum,&g->edgenum,&g->kind)==3); fflush(stdin); printf("input every vertex info: "); for(int i=0;i<g->vexnum;i++){//初始化顶点信息 assert(scanf("%c",&g->vexs[i])==1); fflush(stdin); } char svex,tvex; int weight; switch(g->kind){ case 0://无向图 memset(g->edges,0,sizeof(int)*MAX*MAX); printf("input edges with format i,j "); for(int k=0;k<g->edgenum;k++){ assert(scanf("%c,%c",&svex,&tvex)==2); fflush(stdin); int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=g->edges[j][i]=1; } break; case 1://有向图 memset(g->edges,0,sizeof(int)*MAX*MAX); printf("input edges with format i,j "); for(int k=0;k<g->edgenum;k++){ assert(scanf("%c,%c",&svex,&tvex)==2); fflush(stdin); int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=1; } break; case 2://带权无向图 memset(g->edges,0xFF,sizeof(int)*MAX*MAX); printf("input edges with format i,j,weight "); for(int k=0;k<g->edgenum;k++){ g->edges[k][k]=0; assert(scanf("%c,%c,%d",&svex,&tvex,&weight)==3); fflush(stdin); int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=g->edges[j][i]=weight; } break; case 3://带权有向图 memset(g->edges,0xFF,sizeof(int)*MAX*MAX); printf("input edges with format i,j,weight "); for(int k=0;k<g->edgenum;k++){ g->edges[k][k]=0; assert(scanf("%c,%c,%d",&svex,&tvex,&weight)==3); fflush(stdin); int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=weight; } break; } } //通过文件创建图矩阵 void createMGraphFromFile(MGraph *g,char *file){ assert(g && file); FILE* fp=fopen(file,"r"); assert(fp); char str[256]; if(fgets(str,255,fp)!=NULL){ sscanf(str,"%d,%d,%d",&g->vexnum,&g->edgenum,&g->kind); } for(int i=0;i<g->vexnum;i++){//初始化顶点信息 if(fgets(str,255,fp)!=NULL){ sscanf(str,"%c",&g->vexs[i]); } } char svex,tvex; int weight; switch(g->kind){ case 0://无向图 memset(g->edges,0,sizeof(int)*MAX*MAX); for(int k=0;k<g->edgenum;k++){ if(fgets(str,255,fp)!=NULL){ sscanf(str,"%c,%c",&svex,&tvex); } int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=g->edges[j][i]=1; } break; case 1://有向图 memset(g->edges,0,sizeof(int)*MAX*MAX); for(int k=0;k<g->edgenum;k++){ if(fgets(str,255,fp)!=NULL){ sscanf(str,"%c,%c",&svex,&tvex); } int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=1; } break; case 2://带权无向图 memset(g->edges,0xFF,sizeof(int)*MAX*MAX); for(int k=0;k<g->edgenum;k++){ g->edges[k][k]=0; if(fgets(str,255,fp)!=NULL){ sscanf(str,"%c,%c,%d",&svex,&tvex,&weight); } int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=g->edges[j][i]=weight; } break; case 3://带权有向图 memset(g->edges,0xFF,sizeof(int)*MAX*MAX); for(int k=0;k<g->edgenum;k++){ g->edges[k][k]=0; if(fgets(str,255,fp)!=NULL){ sscanf(str,"%c,%c,%d",&svex,&tvex,&weight); } int i,j; for(i=0;g->vexs[i]!=svex;i++);//找到编号 for(j=0;g->vexs[j]!=tvex;j++); g->edges[i][j]=weight; } break; } } int findVex(MGraph* g,char vex){ for(int i=0;i<g->vexnum;i++) if(g->vexs[i]==vex) return i; return -1; } //最小生成树之Prim,Kruscal算法 //松弛操作 void relaxation(MGraph *g,unsigned int dist[],char vex){ int j=findVex(g,vex); assert(j!=-1); for(int i=0;i<g->vexnum;i++){ if(j==i) dist[i]=0; else if(g->edges[j][i] <dist[i])//<j,i> dist[i]=g->edges[j][i]; } } void relaxation_Dijkstra(MGraph* g,unsigned int dist[],char svex,char tvex){ int i=findVex(g,svex); int j=findVex(g,tvex); assert(j!=-1 && i!=-1); for(int k=0;k<g->vexnum;k++){ if(g->edges[j][k]!=INFINITY && (dist[j]+g->edges[j][k])<dist[k]){ dist[k]=dist[j]+g->edges[j][k]; } } } int findMin(unsigned int dist[],int length){ unsigned int min=INFINITY; int pos=-1; for(int i=0;i<length;i++){ if(dist[i] !=0 && dist[i]<min){ min=dist[i]; pos=i; } } return pos; } //sp[vexnum]标记源点到该点是否已是最短路径 int findMin_Dijkstra(unsigned int dist[],int length,bool sp[]){ unsigned int min=INFINITY; int pos=-1; for(int i=0;i<length;i++){ if(sp[i]==false && dist[i] !=0 && dist[i]<min){ min=dist[i]; pos=i; } } return pos; } void MST_Prim(MGraph* g,char beg_vex){ unsigned int dist[MAX];//辅助数组 char prim_vex[MAX];//记录依次加入的点 int vexs=0;//记录已加入点的数目 prim_vex[vexs++]=beg_vex; relaxation(g,dist,beg_vex); while(vexs<g->vexnum){ int i=findMin(dist,g->vexnum); assert(i!=-1); prim_vex[vexs++]=g->vexs[i]; relaxation(g,dist,g->vexs[i]); } prim_vex[vexs]='