본문 바로가기
C/알고리즘

[C] Prim Algorithm 코드 보완

by 덤더리덤떰 2024. 2. 13.

2023.10.06 - [C/알고리즘] - [C] Prim Alogrithm

 

[C] Prim Alogrithm

1. 신장트리 (Spanning Tree): n개의 정점으로 이루어진 무방향 그래프 G에서 n개의 모든 정점과 n-1개의 간선으로 이루어진 트리 : 사이클 발생하면 안됨 사이클 없이 모든 정점 포함하는 트리 1-1. 최

growingupis.tistory.com

 

PriorityQueue.h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>
#define MAX_HEAP_SIZE 100


typedef struct _HEAP_NODE_ {
	int start;
	int end;
	int distance;
}HEAP_NODE;

typedef struct _HEAP_TREE_ {
	int n;
	HEAP_NODE* heap[MAX_HEAP_SIZE];
}HEAP_TREE;


void insertHeapNode(HEAP_TREE* tr, int start, int end, int distance);
HEAP_NODE* deleteHeapNode(HEAP_TREE* tr);​

 

PriorityQueue.c
#include "PriorityQueue.h"
void insertHeapNode(HEAP_TREE* tr, int start, int end, int distance) {
	if (tr->n >= MAX_HEAP_SIZE) {
		printf("더이상 힙트리에 노드를 삽입할 수 없습니다\n");
		return;
	}

	HEAP_NODE* newNode = (HEAP_NODE*)calloc(1, sizeof(HEAP_NODE));
	assert(newNode != NULL);
	newNode->start = start;
	newNode->end = end;
	newNode->distance = distance;

	tr->heap[++(tr->n)] = newNode;
	int idx = tr->n;
	while (idx != 1 && tr->heap[idx]->distance < tr->heap[idx / 2]->distance) {
		HEAP_NODE* temp = tr->heap[idx];
		tr->heap[idx] = tr->heap[idx / 2];
		tr->heap[idx / 2] = temp;
		idx /= 2;
	}
}

HEAP_NODE* deleteHeapNode(HEAP_TREE* tr) {
	if (tr->n == 0) {
		printf("공백 힙트리이기에 꺼낼 노드가 존재하지 않습니다\n");
		return;
	}
	HEAP_NODE* delNode = tr->heap[1];
	tr->heap[1] = tr->heap[tr->n];
	tr->n--;
	int idx = 1;
	while (idx * 2 <= tr->n && tr->heap[idx]->distance > tr->heap[idx * 2]->distance) {
		int child = idx * 2;
		if (tr->heap[child]->distance > tr->heap[child + 1]->distance) {
			child++;
		}
		HEAP_NODE* temp = tr->heap[child];
		tr->heap[child] = tr->heap[idx];
		tr->heap[idx] = temp;
		idx = child;
	}

	return delNode;
}​

 

Prim.c
#include "PriorityQueue.h"
#define MAX_VERTEX 10

typedef struct GRAPH_NODE {
	int vertex;
	int weight;
	struct GRAPH_NODE* link;
}NODE;

typedef struct {
	NODE* head[MAX_VERTEX];
	int nVertex;
}GRAPH;

int getParent(int *parent, int x){
	if (parent[x] == x) {
		return x;
	}
	else {
		return getParent(parent, parent[x]);
	}
}

int isCycle(int* parent, int x, int y) {
	x = getParent(parent, x);
	y = getParent(parent, y);
	if (x == y) {
		return 1;
	}
	else {
		return 0;
	}
}

void unionParent(int* parent, int x, int y) {
	x = getParent(parent, x);
	y = getParent(parent, y);
	if (x < y) {
		parent[y] = x;
	}
	else {
		parent[x] = y;
	}
}

void insertGraphNode(GRAPH * g, int u,int v, int w){
	if (u >= g->nVertex || v >= g->nVertex) {
		printf("해당 정점은 존재하지 않습니다\n");
		return;
	}
	NODE* newNode = (NODE*)calloc(1, sizeof(NODE));
	newNode->vertex = v;
	newNode->weight = w;
	NODE* curNode = g->head[u];
	NODE* preNode = g->head[u];
	if (curNode == NULL) {
		g->head[u] = newNode;
		return;
	}
	else {
		if (curNode->vertex > v) {
			newNode->link = curNode;
			g->head[u] = newNode;
			return;
		}
		else {
			curNode = curNode->link;
			while (curNode != NULL) {
				if (curNode->vertex > v) {
					break;
				}
				else {
					preNode = curNode;
					curNode = curNode->link;
				}
			}
			newNode->link = preNode->link;
			preNode->link = newNode;
		}
	}
}

void insertVertex(GRAPH* g, int v) {
	if (g->nVertex >= MAX_VERTEX) {
		printf("더이상 정점을 삽입할 수 없습니다\n");
		return;
	}
	else {
		g->nVertex++;
	}
}

void printGraph(GRAPH* g) {
	printf("\n================Print Graph==============\n");
	for (int i = 0; i < g->nVertex; i++) {
		printf("\n정점 %c의 인접 리스트 ", i+'A');
		NODE* cur = g->head[i];
		while (cur != NULL) {
			printf("-> %c", (cur->vertex) + 'A');
			cur = cur->link;
		}
		printf("\n");

	}
}


int PrimAlgorithm(GRAPH* g, int start) {
	printf("\n=================Prim Algorithm 수행===============\n");
	int totalEdge = 0;
	int cost = 0;
	int* parent = (int*)calloc(g->nVertex, sizeof(int));
	assert(parent != NULL);
	for (int i = 0; i < g->nVertex; i++) {
		parent[i] = i;
	}
	bool* visited = (bool*)calloc(g->nVertex, sizeof(bool));
	assert(visited != NULL);

	visited[start] = true;
	HEAP_TREE* tr = (HEAP_TREE*)calloc(1, sizeof(HEAP_TREE));
	assert(tr != NULL);
	//init단계
	NODE* curNode = g->head[start];
	while (curNode) {
		insertHeapNode(tr, start, curNode->vertex, curNode->weight);
		curNode = curNode->link;
	}

	while (totalEdge != g->nVertex-1) {
		HEAP_NODE* now = deleteHeapNode(tr);
		if (visited[now->end] == true || isCycle(parent, now->start, now->end)) {
			continue;
		}
		//방문하지않고 사이클이 발생하지 않는 노드
		visited[now->end] = true;
		unionParent(parent, now->start, now->end);
		cost += (now->distance);
		printf("간선 (%c, %c) %d 선택\n", (now->start) + 'A', (now->end) + 'A', now->distance);
		totalEdge++;
		NODE* p = g->head[now->end];
		while (p != NULL) {
			if (visited[p->vertex] == false) {
				insertHeapNode(tr, now->end, p->vertex, p->weight);
			}
			p = p->link;
		}
	}

	if (totalEdge == g->nVertex - 1) {
		printf("\nComplete Minimum spanning tree with Prim Algorithm ");
		return cost;
	}
}


int main() {
	GRAPH* g = (GRAPH*)calloc(1, sizeof(GRAPH));
	assert(g != NULL);
	for (int i = 0; i < 7; i++) {
		insertVertex(g, i);
	}

	insertGraphNode(g, 0, 1, 3);
	insertGraphNode(g, 0, 2, 17);
	insertGraphNode(g, 0, 3, 6);
	insertGraphNode(g, 1, 0, 3);
	insertGraphNode(g, 1, 3, 5);
	insertGraphNode(g, 2, 0, 17);
	insertGraphNode(g, 2 , 4, 10);
	insertGraphNode(g, 2, 5, 8);
	insertGraphNode(g, 3, 0, 6);
	insertGraphNode(g, 3, 1, 5);
	insertGraphNode(g, 3, 4, 9);
	insertGraphNode(g, 4, 2, 10);
	insertGraphNode(g, 4, 3, 9);
	insertGraphNode(g, 4, 5, 4);
	insertGraphNode(g, 4, 6, 2);
	insertGraphNode(g, 5, 2, 8);
	insertGraphNode(g, 5, 4, 4);
	insertGraphNode(g, 5, 6, 14);
	insertGraphNode(g, 6, 1, 12);
	insertGraphNode(g, 6, 4, 2);
	insertGraphNode(g, 6, 5, 14);
	printGraph(g);
	printf("\n");
	int cost = PrimAlgorithm(g, 0);
	printf("\ntotal cost : %d", cost);


	getchar();
	return 0;

}​

'C > 알고리즘' 카테고리의 다른 글

[C] AVL TREE (코드 보완)  (1) 2024.02.12
[C] 정렬 알고리즘  (0) 2024.02.12
[C] 이진 탐색 트리 (BST)  (0) 2024.02.08
[C] 이중 연결 리스트  (0) 2024.02.06
[C] AVL TREE  (0) 2023.12.10