mojo's Blog

인접 행렬을 이용한 다익스트라 구현 본문

학교에서 들은거 정리/알고리즘설계와분석

인접 행렬을 이용한 다익스트라 구현

_mojo_ 2021. 12. 7. 20:02

인접 행렬을 이용한 다익스트라 알고리즘을 구현한 코드이다.

 

Solution Code

 

/* Dijkstra's algorithm for a digraph in adjacency matrix */
#include <stdio.h>
#include <stdlib.h>

void create_graph(void);
void display(void);
int find_path(int, int, int*, int*);

#define MAX 4096
#define TEMP 0
#define PERM 1

struct node {
	int predecessor;
	int dist; /*minimum distance of node from source*/
	int status;
};

int n, adj[MAX][MAX];

void main() {
	int i, source, dest;
	int path[MAX];
	int shortdist, count;

	// Adjacent Matrix 을 만드는 함수 호출
	create_graph();
	printf("The adjacency matrix is :\n");
	display();

	while (1) {
		printf("Enter source node(-1 to quit) : ");
		scanf("%d", &source);
		printf("Enter destination node(-1 to quit) : ");
		scanf("%d", &dest);

		if (source == -1 || dest == -1) exit(1);

		count = find_path(source, dest, path, &shortdist);
		if (shortdist != 0) { // source ~> dest 로 가는 최단 경로를 찾음
			printf("Shortest distance is : %d\n", shortdist);
			printf("Shortest Path is : ");
			for (i = count; i > 0; i--)
				printf("%d->", path[i]);
			printf("%d", path[0]);
			printf("\n");
		}
		else // 0일 경우 source ~> dest 로 가는 경로가 존재하지 않음!
			printf("There is no path from source to destination node\n");
	}
}

void create_graph(void) {
	int origin, destin, wt;

	printf("Enter number of vertices : ");
	scanf("%d", &n);
	
	// Adjacent Matrix 의 초기화 작업
	for (int i = 0; i < n; i++)
		for (int j = 0; j < n; j++)
			adj[i][j] = 0;

	// origin ~> destin 의 거리 wt 에 대한 Adjacent Matrix 의 세팅과정 
	while (1) {
		printf("Enter next edge (-1 -1 to quit) : ");
		scanf("%d %d", &origin, &destin);
		if ((origin == -1) && (destin == -1))
			break;
		printf("Enter weight for this edge : ");
		scanf("%d", &wt);
		if (origin >= n || destin >= n || origin < 0 || destin < 0 || wt <= 0) {
			printf("Invalid edge (%d, %d, %d)!\n", origin, destin, wt);
		}
		else adj[origin][destin] = wt;
	}
}

void display(void) {
	int i, j;
	for (i = 0; i < n; i++) {
		for (j = 0; j < n; j++)
			printf("%3d", adj[i][j]);
		printf("\n");
	}
}

// Dijkstra algorithm 을 Adjacent Matrix으로 구현한 코드
int find_path(int s, int d, int path[MAX], int* sdist) {
	struct node state[MAX];
	int i, min, current, newdist, u, v;

	/* Make all nodes temporary */
	for (i = 0; i < n; i++) {
		state[i].predecessor = -1; // i번째 노드의 자손을 -1으로 (경로 추적을 위한 용도로 쓰임)
		state[i].dist = INT_MAX; // s번째 노드에서 i번째 노드로 갈 수 있는 최단 거리 
		state[i].status = TEMP; // i번째 노드를 방문했는지에 대한 확인용도
	}

	/* Source node should be permanent */
	state[s].predecessor = s; // 자기 자신을 자손으로 설정하며
	state[s].dist = 0; // 자기 자신으로 가는 경로의 길이는 당연히 0이고
	state[s].status = PERM; // 자기 자신을 방문했으므로 체크

	/* Starting from source node until destination is found */
	current = s; // 현재 위치에 대한 변수
	while (current != d) { // 목적지에 도착할 때까지 반복
		for (i = 0; i < n; i++) {
			/* Checks for adjacent temporary nodes */
			// current ~> i 로 가는 경로가 존재하며 i번째 노드를 방문하지 않은 경우
			if (adj[current][i] > 0 && state[i].status == TEMP) { 
				newdist = state[current].dist + adj[current][i];
				/* Checks for Relabeling */
				if (newdist < state[i].dist) { // current ~> i 로 가는 경로가 기존에 i로 가는 경로에 비해 짧을 경우
					state[i].predecessor = current; // i번째 자손을 current 으로 설정 
					state[i].dist = newdist; // 거리가 더 짧은 걸로 변경해준다.
				}
			}
		}

		/* Search for temporary node with minimum distand make it current node */
		min = INT_MAX; current = -1;
		for (i = 0; i < n; i++) {
			// i번째 노드로 가는 경로중에 가장 최소가 되는 노드를 선별한다.
			if (state[i].status == TEMP && state[i].dist < min) {
				min = state[i].dist;
				current = i;
			}
		}

		// 선별할 수 없을 경우 고립된 경우로 0을 반환함
		if (current == -1) /* If Source or Sink node is isolated */
			return 0;
		// current 로 가는 경로가 가장 최소가 되는 경우가 된 경우이므로 방문 처리를 함
		state[current].status = PERM;
	} /*End of while*/

	/* Getting full path in array from destination to source */
	int count = 0;
	path[count] = current;
	// path 배열에 dest 에서 source 로 역으로 경로를 담아주는 모습이다.
	while (state[current].predecessor != current) { 
		current = state[current].predecessor;
		path[++count] = current;
	}
	/* Getting distance from source to destination */
	// 역으로 담았던 path 배열을 통해 최단 거리의 길이를 반환하도록 한다.
	*sdist = 0;
	for (i = count; i > 0; i--) {
		u = path[i]; v = path[i - 1];
		*sdist += adj[u][v];
	}
	return count;
}

 

'학교에서 들은거 정리 > 알고리즘설계와분석' 카테고리의 다른 글

Prim's Algorithm, Dijkstra's Algorithm  (0) 2021.12.09
Scheduling with Deadlines with Disjoint Sets  (0) 2021.12.07
Disjoint Sets  (0) 2021.11.30
Scheduling with Deadlines  (0) 2021.11.25
Scheduling  (0) 2021.11.23
Comments