图论
来源:互联网 发布:数据库主键怎么定义 编辑:程序博客网 时间:2024/05/22 03:13
图论
这篇文章介绍了几种数据结构中图的算法,最简单的图的搜索dfs和bfs,到高级图的各种算法,如最小生成树,最短路径,关键路径。
图的存储结构
typedef struct{ int arc[MAXVEX][MAXVEX]; int numVertexes,numEdges;}MGraph;
最小生成树Prim算法
这个算法的思想是从任意的一个根节点开始开始,一直长大到覆盖图中所有的节点为止。这边电脑演示比较麻烦,于是手写演示。
void MiniSpanTree_Prim(MGraph G){ int min,i,j,k; int adjvex[MAXVEX]; //保存相关顶点的下标 int lowcost[MAXVEX]; //保存顶点间的权值 lowcost[0] = 0; adjvex[0] = 0; for(i=0;i<G.numVertexes;i++) { lowcost[i] = G.arc[0][i]; //先将第一个顶点包含进去 adjvex[i] = 0; } for(i=1;i<G.numVertexes;i++) { min = INFINITY; j = 1;k=0; while(j<G.numEdges) { if(lowcost[j]!=0 && lowcost[j]<min) //选择当前最小权值的大小和下标 { min = lowcost[j]; k = j; } j++; } printf("(%d,%d)",adjvex[k],k); //输出下标和相连的顶点 lowcost[k] = 0; for(j=1;j<G.numVertexes;j++) //找与k相连的最小的权值的点。 { if(lowcost[j] != 0 && G.arc[k][j]<lowcost[j]) { lowcost[j] = G.arc[k][j]; adjvex[j] = k; } } }}
这个算法还要慢慢看。
Kruskal算法
除了上面的算法之外,还有一种我认为更加经典的算法就是这个了。先贴代码,再解释。
typedef struct{ int begin; int end; int weight;}Edge;void Swapn(Edge *edges,int i,int j){ int temp; temp = edges[i].begin; edges[i].begin = edges[j].begin; edges[j].begin = temp; temp = edges[i].end; edges[i].end = edges[j].end; edges[j].end = temp; temp = edges[i].weight; edges[i].weight = edges[j].weight; edges[j].weight = temp;}void sort(Edge edges[],MGraph *G){ int i,j; for(i=0;i<G->numEdges;i++) for(j=i+1;j<G->numEdges;j++) if(edges[i].weight>edges[j].weight) Swapn(edges,i,j);}int find(int *parent,int f){ while(parent[f]>0) f = parent[f]; return f;}void MinSpanTree_Kruskal(MGraph G){ int i,j,n,m; int k = 0; int parent[MAXVEX]; Edge edges[MAXEDGE]; for(i=0;i<G.numVertexes;i++) { for(j=i+1;j<G.numVertexes;j++) { if(G.arc[i][j]<65535) { edges[k].begin = i; edges[k].end = j; edges[k].weight = G.arc[i][j]; k++; } } } sort(edges,&G); for(i=0;i<G.numEdges;i++) parent[i] = 0; for(i=0;i<G.numEdges;i++) { n = find(parent,edges[i].begin); m = find(parent,edges[i].end); if(n!=m) { parent[n] = m; printf("%d %d %d\n",edges[i].begin,edges[i].end,edges[i].weight); } }}
最短路径
最短路径需要解决的问题是求源点到各个点之间的最短路。这里还分单源最短路径和多源最短路径。单源最短路径算法就是Dijkstra算法,多源最短路径是Floyd算法。
Dijkstra算法
void ShortPath_Dijkstra(MGraph G,int v0,Patharc *P,ShortPathTable *D){ int v,w,k,min; int final[MAXVEX]; for(v=0;v<G.numVertexes;v++) { final[v] = 0; (*D)[v] = G.arc[v0][v]; (*P)[v] = 0; } (*D)[v0] = 0; final[v0] = 1; for(v=1;v<G.numVertexes;v++) { min = INFINITY; for(w = 0;w<G.numVertexes;w++) { if(!final[w] && (*D)[w] < min) { k = w; min = (*D)[w]; } } final[k] = 1; for(w=0;w<G.numEdges;w++) { if(!final[w] && (min + G.arc[k][w] < (*D)[w] )) { (*D)[w] = min + G.arc[k][w]; (*P)[w] = k; } } }}
应该代码能够看得懂的。
Floyd算法
void ShortPath_Floyd(MGraph G,Pathmatirx *P,ShortPathTable *D){ int v,w,k; for(v=0;v<G.numVertexes;v++) { for(w=0;w<G.numVertexes;w++) { (*D)[v][w] = G.arc[v][w]; (*P)[v][w] = w; } } for(k=0;v<G.numVertexes;k++) { for(v = 0;v<G.numVertexes;v++) { for(w = 0;w<G.numVertexes;w++) { if((*D)[v][w] > (*D)[v][k] + (*D)[k][w]) { (*D)[v][w] = (*D)[v][k]+(*D)[k][w]; (*P)[v][w] = (*P)[v][k]; } } } }}
简单粗暴吧。
今天终于将图这部分算法搞懂了,以前一直想学却没有精力和毅力来学习。
1 0