图论

本文探讨图论中的重要算法,包括图的存储结构、Prim算法和Kruskal算法用于构建最小生成树,以及Dijkstra算法和Floyd算法解决最短路径问题。通过学习这些算法,可以深入理解图数据结构及其应用。

图论

这篇文章介绍了几种数据结构中图的算法,最简单的图的搜索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];
                }
            }
        }
    }
}

简单粗暴吧。

今天终于将图这部分算法搞懂了,以前一直想学却没有精力和毅力来学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值