Prim算法(邻接矩阵无相图)求最小生成树 C 实现 ~

核心思想:贪心

算法过程:

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;
2).初始化:V new = {x},其中x为集合V中的任一节点(起始点),E new = {},为空;
3).重复下列操作,直到V new = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合V new中的元素,而v不在V new 集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合V new中,将<u, v>边加入集合E new中;
4).输出:使用集合V new和E new来描述所得到的 最小生成树

核心算法:

void Prim(Graph g, int start)  
{  
	int sum = 0;
	int index = 0;
	int i, j;
	char prims[MAXVEX];
	prims[index++] = g.vex[start];
	
	for(i = 0; i < g.vex_num; i++ ){
		dist[i] = g.edge[start][i];
	}
	dist[start] = 0; //需要 
	int min, u, v;
	int pre;
	for(i = 0; i < g.vex_num; i++ ){
		if(start == i)
			continue;
		min = INFINITY;
		for(j = 0; j < g.vex_num; j++ ){
			if(dist[j] != 0 && dist[j] < min){
				min = dist[j];
				u = j;
			}  
		}
		if(dist[u] != 0)// not really needed anymore. 
			prims[index++] = g.vex[u];
		dist[u]	= 0;
		for(v = 0; v < g.vex_num; v++ ){
			if(dist[v] != 0 && g.edge[u][v] < dist[v])
				dist[v] = g.edge[u][v];
		}
	}
	for(i = 1; i < g.vex_num; i++){
		min = INFINITY;//可以排除u v两点不存在边的情况 
		v = get_pos(g, prims[i]);
		for(j = 0; j < i; j++ ){
			u = get_pos(g, prims[j]);
			if(g.edge[u][v] < min){
				min = g.edge[u][v];	
			}
		}
		sum += min;
	}
	
	printf("prim %c = %d\n",g.vex[start],sum);
	for(i = 0; i < index; i++ ){
		printf("%c",prims[i]);
	}
}  

完整实现:

#include<stdio.h>    
#include<stdlib.h>    
#include<ctype.h>   
#define NOTEXIST -1  
#define BEGIN -1   
#define MAXVEX 100    
#define INFINITY 65535    
#define TRUE 1    
#define FALSE 0     
typedef int EdgeType;  
typedef char VertexType;    
int dist[MAXVEX];  //dist指 从 该点到被收录的各点中 距离的最小值 
typedef struct Graph {  
    VertexType vex[MAXVEX];  
    EdgeType edge[MAXVEX][MAXVEX];  
    int vex_num, edge_num;  
}Graph;  
  
char read_char()  
{  
    char ch;  
    do {  
        ch = getchar();  
    } while (!isalpha(ch));  
    return ch;  
}  
  
int get_pos(Graph g, char ch)  
{  
    int i;  
    for (i = 0; i < g.vex_num; i++) {  
        if (g.vex[i] == ch)  
            return i;  
    }  
    return -1;  
}  
  
void create_graph(Graph *g)  
{  
    int i, j, k;  
    printf("请输入顶点数与边数:\n");    
    scanf("%d%d", &g->vex_num, &g->edge_num);  
    for (i = 0; i < g->vex_num; i++) {  
        for (j = 0; j < g->vex_num; j++) {  
            if (i == j) {  
                g->edge[i][j] = 0;  
            }  
            else  
                g->edge[i][j] = INFINITY;  
        }  
    }  
    printf("请输入顶点信息:\n");    
    for (i = 0; i < g->vex_num; i++) {    
        g->vex[i] = read_char();  
    }  
    printf("请输入边的信息:\n");    
    char c1, c2;  
    int p1, p2, w;  
    for (k = 0; k < g->edge_num; k++) {  
        c1 = read_char();  
        c2 = read_char();  
        scanf("%d", &w);  
        p1 = get_pos(*g, c1);  
        p2 = get_pos(*g, c2);  
        g->edge[p1][p2] = w;//有向边的权重   
		g->edge[p2][p1] = w; 
    }  
}  
  
void Prim(Graph g, int start)  
{  
	int sum = 0;
	int index = 0;
	int i, j;
	char prims[MAXVEX];
	prims[index++] = g.vex[start];
	
	for(i = 0; i < g.vex_num; i++ ){
		dist[i] = g.edge[start][i];
	}
	dist[start] = 0; //需要 
	int min, u, v;
	int pre;
	for(i = 0; i < g.vex_num; i++ ){
		if(start == i)
			continue;
		min = INFINITY;
		for(j = 0; j < g.vex_num; j++ ){
			if(dist[j] != 0 && dist[j] < min){
				min = dist[j];
				u = j;
			}  
		}
		if(dist[u] != 0)// not really needed anymore. 
			prims[index++] = g.vex[u];
		dist[u]	= 0;
		for(v = 0; v < g.vex_num; v++ ){
			if(dist[v] != 0 && g.edge[u][v] < dist[v])
				dist[v] = g.edge[u][v];
		}
	}
	for(i = 1; i < g.vex_num; i++){
		min = INFINITY;//可以排除u v两点不存在边的情况 
		v = get_pos(g, prims[i]);
		for(j = 0; j < i; j++ ){
			u = get_pos(g, prims[j]);
			if(g.edge[u][v] < min){
				min = g.edge[u][v];	
			}
		}
		sum += min;
	}
	
	printf("prim %c = %d\n",g.vex[start],sum);
	for(i = 0; i < index; i++ ){
		printf("%c ",prims[i]);
	}
}  
  
void print_graph(Graph g)  
{  
    int i, j;  
    for (i = 0; i < g.vex_num; i++) {  
        for (j = 0; j < g.vex_num; j++) {  
            if (g.edge[i][j] == INFINITY)  
                printf("%5c", '*');  
            else {  
                printf("%5d", g.edge[i][j]);  
            }  
        }  
        printf("\n");  
    }  
}   
  
int main()  
{  
    Graph g;  
    int start, end;  
    char c1;
    create_graph(&g);  
    printf("请输入起始点:\n");  
    c1 = read_char(); 
    start = get_pos(g, c1);         
    Prim(g, start);  
    getchar();  
    return 0;  
} 



  • 3
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值