数据结构与算法学习之路:Prim算法和Kruskal算法

一、Prim算法和Kruskal算法是什么?

Prim算法:首先把图中所有顶点看作未被访问的点的点集——>随意挑选其中一个点,并把该点放入已被访问过的点的点集——>不断的寻找与被访问点集中的点距离最短的,并且未被访问过的点,加入被访问点集——>当所有点都进入被访问点集,则获得图的最小生成树。


Prim算法查找过程:

数据结构与算法学习之路:Prim算法和Kruskal算法_第1张图片

Kruskal算法:获得图中所有具有权值的边,从中挑选权值最小的边,若边会与已挑选边形成回路,则该边;不形成回路,则加入最小生成树。


Kruskal算法查找过程:


二、各自的优缺点是什么?

主要差异在于,Prim算法在面对稠密图时效率较高,Kruskal算法在面对稀疏图时效率更高。


三、具体代码

Prim算法:

#include <stdio.h>
#include <stdlib.h>

#define VISITED 1
#define UNVISITED 0

#define GRAPH_SIZE 6
#define EDGE_MAXLENGTH 32767

typedef struct EdgeCost{
	int cost, vex;
};

void Prim(int(*graph)[GRAPH_SIZE], EdgeCost *lowcost, int *visited);

int main(){
	//记录被选出的点到达未被选出点的最小权值边
	//如:已选出点:v0,未被选出点:v1,v2,v3,v4,v5,则lowcost[4].cost代表v0到达v4的最小权值,lowcost[4].vex在此表示边的起点是v0
	EdgeCost lowcost[GRAPH_SIZE];
	//用于标记点是否被访问
	int visited[GRAPH_SIZE];
	//图
	int graph[GRAPH_SIZE][GRAPH_SIZE];

	int i, j;

	//初始化
	for (i = 0; i < GRAPH_SIZE; i++){
		visited[i] = 0;
		lowcost[i].cost = EDGE_MAXLENGTH;
		lowcost[i].vex = -1;
	}

	for (i = 0; i < GRAPH_SIZE; i++)
		for (j = 0; j < GRAPH_SIZE; j++)
			graph[i][j] = EDGE_MAXLENGTH;

	graph[0][1] = 7;
	graph[1][0] = 7;
	graph[0][2] = 1;
	graph[2][0] = 1;
	graph[0][3] = 5;
	graph[3][0] = 5;
	graph[2][1] = 5;
	graph[1][2] = 5;
	graph[2][3] = 5;
	graph[3][2] = 5;
	graph[2][4] = 8;
	graph[4][2] = 8;
	graph[2][5] = 4;
	graph[5][2] = 4;
	graph[1][4] = 3;
	graph[4][1] = 3;
	graph[3][5] = 2;
	graph[5][3] = 2;
	graph[4][5] = 6;
	graph[5][4] = 6;

	for (i = 0; i < GRAPH_SIZE; i++){
		for (j = 0; j < GRAPH_SIZE; j++)
			printf("%d\t", graph[i][j]);
		printf("\n");
	}
	printf("\n");

	//Prim算法,选择从v0开始
	visited[0] = VISITED;
	for (i = 1; i < GRAPH_SIZE; i++){
		if (graph[0][i] != EDGE_MAXLENGTH){
			lowcost[i].vex = 0;
			lowcost[i].cost = graph[0][i];
		}
	}
	Prim(graph, lowcost, visited);
}

void Prim(int(*graph)[GRAPH_SIZE], EdgeCost *lowcost, int *visited){
	int i, vex, adj, min = EDGE_MAXLENGTH, result = 0;

	for (i = 0; i < GRAPH_SIZE; i++){
		if (visited[i] != VISITED && lowcost[i].cost < min){
				adj = i;
				vex = lowcost[i].vex;
				min = lowcost[i].cost;
		}else if (visited[i] == VISITED)
			result++;
	}

	if (result == GRAPH_SIZE)
		return;

	visited[adj] = VISITED;
	printf("( %d, %d)   ", vex, adj);
	for (i = 0; i < GRAPH_SIZE; i++){
		if (graph[adj][i] < lowcost[i].cost){
			lowcost[i].vex = adj;
			lowcost[i].cost = graph[adj][i];
		}
	}

	Prim(graph, lowcost, visited);
}

Kruskal算法:

<span style="font-size:12px;">#include <stdio.h>
#include <stdlib.h>

#define VISITED 1
#define UNVISITED 0

#define MAX_EDGES 20
#define GRAPH_SIZE 6
#define EDGE_MAXLENGTH 32767


typedef struct Edge{
	int pre, back, weight;
}Edge;

int FindRoot(int *root, int point);
void Kruscal(Edge *edges, int *root);

int main(){
	Edge edges[MAX_EDGES];
	int root[GRAPH_SIZE];
	int graph[GRAPH_SIZE][GRAPH_SIZE];

	int i, j, k = 0;

	//初始化图
	for (i = 0; i < GRAPH_SIZE; i++)
		for (j = 0; j < GRAPH_SIZE; j++)
			graph[i][j] = EDGE_MAXLENGTH;

	graph[0][1] = 7;
	graph[1][0] = 7;
	graph[0][2] = 1;
	graph[2][0] = 1;
	graph[0][3] = 5;
	graph[3][0] = 5;
	graph[2][1] = 5;
	graph[1][2] = 5;
	graph[2][3] = 5;
	graph[3][2] = 5;
	graph[2][4] = 8;
	graph[4][2] = 8;
	graph[2][5] = 4;
	graph[5][2] = 4;
	graph[1][4] = 3;
	graph[4][1] = 3;
	graph[3][5] = 2;
	graph[5][3] = 2;
	graph[4][5] = 6;
	graph[5][4] = 6;

	//初始化可达的边集
	for (i = 0; i < GRAPH_SIZE; i++){
		for (j = 0; j < GRAPH_SIZE; j++){
			if (graph[i][j] < EDGE_MAXLENGTH){
				edges[k].pre = i;
				edges[k].back = j;
				edges[k].weight = graph[i][j];
				k++;
			}
		}
	}

	//初始化边的根节点数组
	for (i = 0; i < GRAPH_SIZE; i++)
		root[i] = 0;

	for (i = 0; i < GRAPH_SIZE; i++){
		for (j = 0; j < GRAPH_SIZE; j++)
			printf("%d\t", graph[i][j]);
		printf("\n");
	}
	printf("\n");
	Kruscal(edges, root);
}

int FindRoot(int *root, int point){
	while (root[point] > 0)
		point = root[point];

	return point;
}

void Kruscal(Edge *edges, int *root){
	int i, j, min, pre, back, visited, weight, buf, edf;

	for (i = 0; i < MAX_EDGES; i++){
		min = EDGE_MAXLENGTH;
		for (j = 0; j < MAX_EDGES; j++){
			if (edges[j].weight < min){
				pre = edges[j].pre;
				back = edges[j].back;
				min = edges[j].weight;
				visited = j;
			}
		}
		buf = FindRoot(root, pre);
		edf = FindRoot(root, back);
		edges[visited].weight = EDGE_MAXLENGTH;
		if (buf != edf){
			root[buf] = edf;
			printf("(%d, %d)", pre, back, min);
		}
	}
}</span>


你可能感兴趣的:(数据结构与算法学习之路:Prim算法和Kruskal算法)