圖論

圖論

這篇文章介紹了幾種數據結構中圖的算法,最簡單的圖的搜索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];
                }
            }
        }
    }
}

簡單粗暴吧。

今天終於將圖這部分算法搞懂了,以前一直想學卻沒有精力和毅力來學習。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章