1. 程式人生 > 實用技巧 >最小生成樹MST

最小生成樹MST

最小生成樹(Minimum Spanning Trees)

//kruskal-->MST
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct Edge {
	int src, dest, weight;
}Edge;

typedef struct Graph {
	int V, E;	//V: 總節點數  E: 總邊數
	Edge* edge;
}Graph;

Graph* createGraph(int V, int E) {
	Graph* graph = new Graph;
	graph->V = V;
	graph->E = E;
	graph->edge = new Edge[E];

	return graph;
}
//union-find  並查集
typedef struct subset {
	int parent;
	int rank;	//子樹深度,合併時用
}subset;

int find(subset subsets[], int i) {
	if (subsets[i].parent != i)
		subsets[i].parent = find(subsets, subsets[i].parent);
	return subsets[i].parent;
}
//合併 集合
void Union(subset subsets[], int x, int y) {
	int xroot = find(subsets, x);
	int yroot = find(subsets, y);

	if (subsets[xroot].rank < subsets[yroot].rank)
		subsets[xroot].parent = yroot;
	else if (subsets[xroot].rank > subsets[yroot].rank)
		subsets[yroot].parent = xroot;
	else {
		subsets[yroot].parent = xroot;
		subsets[xroot].rank++;
	}
}

int mycomp(const void* a, const void* b) {
	//	return ((Edge*)a)->weight > ((Edge*)b)->weight;
	return (*(Edge*)a).weight > (*(Edge*)b).weight;
}

/*
*邊排序-> 遍歷-> 符合條件加入
*/
void KruskalMST(Graph* graph) {
	int V = graph->V;
	Edge* result = (Edge*)malloc(V * sizeof(Edge));
	int e = 0;
	int i = 0;
	qsort(graph->edge, graph->E, sizeof(graph->edge[0]), mycomp);

	subset* subsets = (subset*)malloc(V * sizeof(subset));
	for (int v = 0; v < V; v++) {	//初始化V個並查集
		subsets[v].parent = v;
		subsets[v].rank = 0;
	}
	/*-------核心程式碼--------*/
	while (e < V - 1 && i < graph->E) {		//V個點,V-1條邊
		Edge minEdge = graph->edge[i++];
		int x = find(subsets, minEdge.src);
		int y = find(subsets, minEdge.dest);

		if (x != y) {
			result[e++] = minEdge;
			Union(subsets, x, y);
		}
	}
	/*--------------------*/
	printf("edges in MST:\n");
	int minCost = 0;
	for (i = 0; i < e; i++) {
		printf("%d ------ %d == %d\n", result[i].src, result[i].dest, result[i].weight);
		minCost += result[i].weight;
	}
	printf("minCost: %d\n", minCost);
	return;
}

int main() {
	//煮個栗子
	int V = 4;
	int E = 5;
	Graph* graph = createGraph(V, E);

	graph->edge[0].src = 0;
	graph->edge[0].dest = 1;
	graph->edge[0].weight = 10;

	graph->edge[1].src = 0;
	graph->edge[1].dest = 2;
	graph->edge[1].weight = 6;

	graph->edge[2].src = 0;
	graph->edge[2].dest = 3;
	graph->edge[2].weight = 5;

	graph->edge[3].src = 1;
	graph->edge[3].dest = 3;
	graph->edge[3].weight = 15;

	graph->edge[4].src = 2;
	graph->edge[4].dest = 3;
	graph->edge[4].weight = 4;

	KruskalMST(graph);
	return 0;
}