数据结构 图 最小生成树

(1)Prim

算法如下,头文件:

#define INFINITY 10000
#define MAX_VERTEX_NUM 20

typedef 
int InfoType;
typedef 
char VertexType;
typedef 
int VRType;

typedef 
enum {DG, DN, UDG, UDN} GraphKind;

typedef 
struct ArcCell{
    VRType adj;
    InfoType 
*info;
}
ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef 
struct{
    VertexType vexs[MAX_VERTEX_NUM];
    AdjMatrix arcs;
    
int vexnum, arcnum;
    GraphKind kind;
}
MGraph;

int weight[][6= {
    
{0615, INFINITY,INFINITY},
    
{605, INFINITY, 3, INFINITY},
    
{150564},
    
{5, INFINITY, 50, INFINITY, 2},
    
{INFINITY, 36, INFINITY, 06},
    
{INFINITY, INFINITY, 4260}
}
;

//#define INPUT 1

typedef 
struct {
    
int parent;
    
int cost;
}
mst_prim_closedge;

源文件:

#include "graph.h"
#include 
"stdio.h"
#include 
"stdlib.h"

void createDG(MGraph &g){}
void createDN(MGraph &g){}
void createUDG(MGraph &g){}

int locate(MGraph g, char name){
    
for(int i = 0; i < g.vexnum; i++){
        
if(name == g.vexs[i]){
            
return i;
        }

    }

    
return -1;
}


void createUDN(MGraph &g){
    
#ifdef INPUT
    printf(
"input the number of vertex and arcs: ");
    scanf(
"%d %d"&g.vexnum, &g.arcnum);
    fflush(stdin);
#else
    printf(
"input the number of vertex: ");
    scanf(
"%d"&g.vexnum);
    fflush(stdin);
#endif
    
    
int i = 0, j = 0, k = 0;
    
    printf(
"input the name of vertex: ");
    
    
for(i = 0; i < g.vexnum; i++){
        scanf(
"%c"&g.vexs[i]);
        fflush(stdin);
    }

    
    
for(i = 0; i < g.vexnum; i++){
        
for(j = 0; j < g.vexnum; j++){
            g.arcs[i][j].adj 
= INFINITY;
            g.arcs[i][j].info 
= NULL;
        }

    }

    
#ifdef INPUT
    
char v1, v2;
    
int w;
    printf(
"input the %d arcs v1 v2 and weight: ", g.arcnum);
    
for(k = 0; k < g.arcnum; k++){
        scanf(
"%c %c %d"&v1, &v2, &w);
        fflush(stdin);
        i 
= locate(g, v1);
        j 
= locate(g, v2);
        g.arcs[i][j].adj 
= w;
    }

#else
    printf(
"now constructing the matrix of graph... ");
    
for(i = 0; i < g.vexnum; i++){
        
for(j = 0; j < g.vexnum; j++){
            g.arcs[i][j].adj 
= weight[i][j];
        }

    }

#endif
}


void printGraph(MGraph g){
    
for(int i = 0; i < g.vexnum; i++){
        
for(int j = 0; j < g.vexnum; j++){
            printf(
"%d ", g.arcs[i][j].adj);
        }

        printf(
" ");
    }

}


void createGragh(MGraph &g){
    
    printf(
"please input the type of graph: ");
    scanf(
"%d"&g.kind);
    
    
switch(g.kind){
    
case DG: 
        createDG(g);
        
break;
    
case DN: 
        createDN(g);
        
break;
    
case UDG: 
        createUDG(g);
        
break;
    
case UDN: 
        createUDN(g);
        printGraph(g);
        
break;
    }

}


//get the min cost vertice, return the index
int minimum(mst_prim_closedge *closedge, int n){
    
int ret = -1;
    
int retcost = INFINITY;
    
for(int i = 0; i < n; i++){
        
if(closedge[i].cost > 0 && closedge[i].cost < retcost){
            ret 
= i;
            retcost 
= closedge[i].cost;
        }

    }

    
return ret;
}


/**
 * the prim algorithm of mst(minimum cost spanning tree)
 * MGraph g: the graph
 * char start: the start point
 
*/

void mst_prim(MGraph g, char start){
    mst_prim_closedge 
*closedge = 
        (mst_prim_closedge 
*)malloc(sizeof(mst_prim_closedge) * g.vexnum);

    
//get the index of start
    int index = locate(g, start);

    
//init the closest edge array
    int i = 0;
    
for(; i < g.vexnum; i++){
        closedge[i].parent 
= index;
        closedge[i].cost 
= g.arcs[index][i].adj;
    }


    
//choose the next n-1 vertex
    printf("now the mst is: ");
    
int j = 0;
    
for(i = 1; i < g.vexnum; i++){
        j 
= minimum(closedge, g.vexnum);
        printf(
"%c, %c, %d "
            g.vexs[closedge[j].parent], g.vexs[j], closedge[j].cost);

        
//j join the U 
        closedge[j].cost = 0;

        
//update the closedge
        for(int k = 0; k < g.vexnum; k++){
            
if(g.arcs[j][k].adj > 0 && 
                g.arcs[j][k].adj 
< closedge[k].cost){
                closedge[k].cost 
= g.arcs[j][k].adj;
                closedge[k].parent 
= j;
            }

        }

    }

}


void main(){
    MGraph g;
    createGragh(g);

    
char start;
    printf(
"input the start point of mst: ");
    scanf(
"%c"&start);
    mst_prim(g, start);
}

程序的执行结果为:

please input the type of graph:
3
input the number of vertex:
6
input the name of vertex:
a
b
c
d
e
f
now constructing the matrix of graph...
0       6       1       5       10000   10000
6       0       5       10000   3       10000
1       5       0       5       6       4
5       10000   5       0       10000   2
10000   3       6       10000   0       6
10000   10000   4       2       6       0
input the start point of mst:
a
now the mst is:
a, c, 
1
c, f, 
4
f, d, 
2
c, b, 
5
b, e, 
3
Press any key 
to continue

 算法的复杂度:从函数mst_prim()可知,时间复杂度为O(n*n),适用于求边稠密的network的mst。

(2)Kruskal

时间复杂度为O(e*log(e)),适用于求边稀疏的network的mst。

算法思想:“等价类,并查集,边排序,选小边”。

代码如下,头文件添加:

typedef struct {
    
int v1;
    
int v2;
    
int cost;
    
int used;
}
mst_kruskal_edge;

源文件添加:

//get the class of i
int findparent(int *parent, int i){
    
while(parent[i] != -1){
        i 
= parent[i];
    }

    
return i;
}


//get the smallest edge that has not used
int getMin(mst_kruskal_edge *edge, int num){
    
int cost = INFINITY, index = -1;
    
for(int i = 0; i < num; i++){
        
if(edge[i].used == 0 && edge[i].cost < cost){
            cost 
= edge[i].cost;
            index 
= i;
        }

    }

    
return index;
}


/**
 * the kruskal of mst
 
*/

void mst_kruskal(MGraph g){
    
//first construct the edge array
    mst_kruskal_edge *edge = (mst_kruskal_edge *)
        malloc(
sizeof(mst_kruskal_edge) * g.vexnum / 2 * (g.vexnum - 1));
    
int i, j, k = 0;
    
for(i = 0; i < g.vexnum; i++){
        
for(j = i + 1; j < g.vexnum; j++){
            
if(g.arcs[i][j].adj > 0 && g.arcs[i][j].adj != INFINITY){
                edge[k].v1 
= i;
                edge[k].v2 
= j;
                edge[k].cost 
= g.arcs[i][j].adj;
                
//this edge is not used
                edge[k].used = 0;
                k
++;
            }

        }

    }

    printf(
"the num of edge is : %d ", k);

    
//the parent array, represent the class of the vertice
    int *parent = (int *)malloc(sizeof(int* g.vexnum);

    
//init it with -1
    for(i = 0; i < g.vexnum; i++){
        parent[i] 
= -1;
    }


    
//construct the mst
    printf("now constructing the mst... ");
    
for(i = 0; i < k; i++){
        
int index = getMin(edge, k);
        
if(index != -1){
            
int p1 = findparent(parent, edge[index].v1);
            
int p2 = findparent(parent, edge[index].v2);
            
if(p1 != p2){
                printf(
"%c, %c, %d "
                    g.vexs[edge[index].v1], g.vexs[edge[index].v2], edge[index].cost);
                parent[p2] 
= p1;
            }

            edge[index].used 
= 1;
        }
else{
            
break;
        }

    }

}


void main(){
    MGraph g;
    createGragh(g);

    
/*
    char start;
    printf("input the start point of mst: ");
    scanf("%c", &start);
    mst_prim(g, start);
    
*/


    mst_kruskal(g);
}

程序的执行结果为:

please input the type of graph:
3
input the number of vertex:
6
input the name of vertex:
a
b
c
d
e
f
now constructing the matrix of graph...
0       6       1       5       10000   10000
6       0       5       10000   3       10000
1       5       0       5       6       4
5       10000   5       0       10000   2
10000   3       6       10000   0       6
10000   10000   4       2       6       0
the num of edge 
is : 10
now constructing the mst...
a, c, 
1
d, f, 
2
b, e, 
3
c, f, 
4
b, c, 
5
Press any key to 
continue

说明:kruskal至多对e条边各扫描一次,上面的查找算法的复杂度是O(e),所以实现的kruskal的复杂度是O(e*e)。但是如果使用堆排序,每次的查找复杂度可以变成O(log(e))(第一次需要O(e)来建立堆),从而Kruskal的复杂度是O(e * log(e))。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值