Data Structure – Prim Algorithm

MST: 프림 알고리즘

‘부분 트리에 속한 정점’과 ‘인접한 정점’ 사이의 에지 중 가중치가 최소인 에지를 선택한다. n-1개의 에지가 선택될 때까지 진행한다. prim으로 인해 만들어진 부분트리를 S, 나머지 정점들을 T라고 놓고 문제를 접근한다.


프림 알고리즘 구현

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

#define TRUE 1
#define FALSE 0
#define MAX_VERTICES 100
#define INF 1000L

typedef struct GraphType {
	int n;
	int weight[MAX_VERTICES][MAX_VERTICES];
}GraphType;

int selected[MAX_VERTICES]; // <테이블의 s/t열> , 선택되면 s집합에 속함 
int w[MAX_VERTICES]; // <테이블의 w열> , 원소: s집합에서 해당 정점까지의 거리 

// 현재 테이블(s/t,w) 상태 출력 
void print_status(GraphType* g) {
	printf("\nS/T: ");
	for (int i = 0; i < g->n; i++)
		printf("%2d ", selected[i]);
	printf("\n");
	printf("W:   ");
	for (int i = 0; i < g->n; i++) {
		if (w[i] == INF)
			printf("INF ");
		else
			printf("%2d ", w[i]);
	}
	printf("\n");
}

// s집합에 속하지 않으면서 최소 w[v] 값을 갖는 정점을 반환
int get_min_vertex(int n) {
	int v, i;
	// 선택되지 않은 정점을 선택 (v정점 지정) 
	for (i = 0; i < n; i++) {
		if (!selected[i]) {
			v = i;
			break;
		}
	}
	// v정점의 w값과 나머지 정점들의 w값을 비교하면서 최소 w값을 갖는 정점 구하기 (선택된 것은 제외) 
	for (i = 0; i < n; i++) {
		if (!selected[i] && (w[i] < w[v]))
			v = i;
	}
	return v;
}

void prim(GraphType* g, int s) {
	int i, u, v;

	// s집합에 원소가 없으면 a(0)만 인접하다고 가정하고 문제를 풀음 
	for (u = 0; u < g->n; u++)
		w[u] = INF;
	w[s] = 0;

	// s집합에 원소가 한 개 이상 있을 때 반복문으로 문제 풀기 (정점을 n개 선택할 때까지)
	for (i = 0; i < g->n; i++) {
		print_status(g);
		// w배열에서 가중치가 가장 작은 정점 선택 (s에 속하지 않은 정점들로 한정) 
		u = get_min_vertex(g->n);
		selected[u] = TRUE;
		if (w[u] == INF) {
			printf("-> 선택할 정점이 없음\n");
			return;
		}
		else
			printf("-> 정점 %c 선택\n", u+97);

		// s집합과 인접한 정점들로 w배열 업데이트
		for (v = 0; v < g->n; v++) {
			// u정점을 기준으로 인접한 것을 찾음 <u정점 말고 다른 정점도 s집합에 속하지만 같은 배열을 업데이트하는 개념이므로, 이미 처리가 된 상태임>
			if (g->weight[u][v] != INF) {
				if (!selected[v] && g->weight[u][v] < w[v]) // v정점이 s집합에 속하면 처리 x, u-v의 가중치가 기존의 w배열 원소보다 작으면 업데이트 
					w[v] = g->weight[u][v];
			}
		}
	}
}

int main(void) {

	// a(0)부터 g(7)까지를 정점으로 가지는 그래프 
	GraphType g = { 8,{
		{0,2,INF,3,INF,INF,INF,INF},
		{2,0,5,4,INF,INF,INF,INF},
		{INF,5,0,4,INF,INF,INF,6},
		{3,4,4,0,1,2,INF,7},
		{INF,INF,INF,1,0,5,7,INF},
		{INF,INF,INF,5,5,0,8,INF},
		{INF,INF,INF,INF,7,8,0,INF},
		{INF,INF,6,7,INF,INF,INF,0}
		}
	};
	prim(&g, 0);
	return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *