图论
这篇文章介绍了几种数据结构中图的算法,最简单的图的搜索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];
}
}
}
}
}
简单粗暴吧。
今天终于将图这部分算法搞懂了,以前一直想学却没有精力和毅力来学习。