네이버 이웃 추가 / GitHub Profile / 카카오톡 채널 추가 / 방명록 / 이용 안내

C++ 다익스트라 알고리즘으로 최단 경로 구하기

수성컴 | 2026. 03. 02.
C++ 다익스트라 알고리즘으로 최단 경로 구하기

지도를 보면 여러 점이 있고 길마다 거리가 다릅니다. 이때 한 점에서 다른 점으로 이동하기 위한 최단 경로는 어떻게 구할 수 있을까요? 다익스트라 알고리즘(Dijkstra Algorithm)으로 구할 수 있습니다. 오늘은 C++로 다익스트라 알고리즘을 구현해 보겠습니다.

목차

1. 파일 목록
2. class 상속 관계
3. 파일 입력
4. ★★다익스트라 알고리즘
5. ★출발 지점으로부터 도착 지점까지의 최단 경로 및 최단 거리 구하기
6. 나머지는 GitHub repository를 참고하세요.
7. 글 마무리
8. 참고 자료

1. 파일 목록

  • .gitignore: x64(folder), *.vcxproj, *.vcxproj.filters, *.vcxproj.user, *.txt, *.o, run을 무시
  • Graph.cpp: Graph의 멤버 변수/함수
  • Graph.h: 그래프를 위한 class
  • LICENSE: MIT License
  • ListGraph.cpp: ListGraph의 멤버 변수/함수
  • ListGraph.h: list graph를 위한 class
  • main.cpp: 콘솔 입출력을 담당하는 main 함수
  • makefile: make를 사용하여 빌드하기 위한 파일
  • Manager.cpp: Manager의 멤버 변수/함수
  • Manager.h: 함수들을 작동시키기 위한 class
  • MatrixGraph.cpp: MatrixGraph의 멤버 변수/함수
  • MatrixGraph.h: matrix graph를 위한 class

이 글은 일부 코드만 설명합니다. 전체 코드는 https://github.com/sooseongcom/Dijkstra에서 확인하실 수 있습니다.

2. class 상속 관계

Inheritance
ListGraph와 MatrixGraph는 Graph를 상속받습니다.

3. 파일 입력

그래프를 텍스트 파일(*.txt)로 작성합니다. List Graph와 Matrix Graph를 지원하며 양식은 아래와 같습니다.

3.1. List Graph

L
v 0
e 1 2
e 2 5
e 3 1
v 1
e 2 3
e 3 3
v 2
e 1 3
e 5 2
v 3
e 2 4
e 4 1
v 4
e 2 2
e 5 1
v 5
e 5 0

[Line 1]
L은 List Graph라는 뜻입니다.

[Line 2~]

  • v <from>: vertex를 만들고 선택합니다.
  • e <to> <weight>: 선택된 vertex(<from>)부터 <to> 까지 연결해 주는 edge를 작성합니다. 거리는 <weight>입니다.
  • 선택된 vertex에서 출발하여 다른 vertex로 가는 edge가 있을 경우 자기 자신으로 가는 edge(거리가 0인 edge)는 생략할 수 있습니다. 다만, 선택된 vertex에서 출발하여 다른 vertex로 가는 edge가 없을 경우 자기 자신으로 가는 edge를 거리 0으로 선언해 주시기 바랍니다(19행 참조).

3.2. Matrix Graph

M
6
0 2 5 1 0 0
0 0 3 3 0 0
0 3 0 0 2 0
0 0 4 0 1 0
0 0 2 0 0 1
0 0 0 0 0 0

[Line 1]
M은 Matrix Graph라는 뜻입니다.

[Line 2]
vertex 개수를 적어 줍니다.

[Line 3~]
Matrix graph를 작성합니다. 열과 열 사이는 공백으로 구분합니다.

4. ★★다익스트라 알고리즘

다익스트라 알고리즘은 출발 지점으로부터 모든 지점까지의 최단 거리를 구하는 알고리즘입니다. 모든 선(edge)은 방향성이 있습니다. 출발 지점(vertex)을 parameter로 입력받는 dijkstra 함수와 vertex에 0을 대입한 예시로 설명 드리겠습니다.

//Graph.cpp Line 12~46
int Graph::dijkstra(int vertex) {
	arraysInit();	//Init dist, prev, visited

	map<int, int> adjacentEdges;
	getAdjacentEdges(vertex, &adjacentEdges);
	
	for (auto iter = adjacentEdges.begin(); iter != adjacentEdges.end(); iter++) {
		setVisited(iter->first, false);
		setDistance(iter->first, iter->second);
		setPrev(iter->first, vertex);
	}

	setVisited(vertex, true);
	setDistance(vertex, 0);
	
	while(1) {
		int u = choose();	//choose() returns a value u such that getDistance(u) = minimum getDistance(w) where visited[w]=false
		if (u == -1 || getVisited(u) == true) break;

		setVisited(u, true);
		getAdjacentEdges(u, &adjacentEdges);

		for (auto iter = adjacentEdges.begin(); iter != adjacentEdges.end(); iter++) {
			if (getVisited(iter->first) == false) {
				int u_dist = getDistance(u);
				if (getVisited(iter->first) == false && u_dist + iter->second < getDistance(iter->first)) {
					setDistance(iter->first, u_dist + iter->second);
					setPrev(iter->first, u);
				}
			}
		}
	}

	return 0;
}

위 코드블록의 행 번호를 기준으로 설명 드리겠습니다.

[Line 3]
Dijkstra init
dist와 prev는 int형 배열, visited는 bool형 배열입니다. dist의 모든 원소를 MAX(적당히 큰 숫자. 저는 0xfffffff로 했습니다.)로, visited의 모든 원소를 false로, prev의 모든 원소를 false로 초기화합니다. (함수 별도 구현)

[Line 5~6]
adjacentEdges는 연결된 edge를 저장하기 위한 map입니다. key는 vertex 번호이고, value는 거리입니다. getAdjacentEdges 함수를 이용하여 vertex로부터 연결된 edge를 구합니다.(함수 별도 구현)

[Line 8~12]
Dijkstra-0
adjacentEdges에 저장된 정보를 이용하여 dist를 최단 거리로 업데이트하고 0번 vertex와 edge로 연결된 vertex의 prev를 0으로 설정합니다.
그러고 나서 visited[0]=true;를 실행합니다.

[Line 17~33]
Dijkstra-3
choose() 함수를 이용하여 아직 방문하지 않은 vertex 중 가장 가까운 vertex를 선택합니다(함수 별도 구현). 이번에는 3이네요.
visited[3]=true;를 실행합니다.
연결된 vertex는 2와 4가 있네요. 거리를 비교해 보면
2: 5==1+4 ⇒ dist[2]와 prev[2] 유지
4: MAX>1+1 ⇒ dist[4]=2; prev[4]=3;
이렇게 진행됩니다.

모든 vertex를 방문할 때까지 Line 20~38을 계속 반복합니다. 예시를 이어서 보겠습니다.

Dijkstra-1
아직 방문하지 않은 vertex 중 가장 가까운 vertex는 1입니다.
visited[1]=true;를 실행합니다.
연결된 vertex는 2가 있습니다.(3도 있지만 이미 방문했으므로 건너뜀.)
거리를 비교해 보면 5==2+3이므로 dist[2]와 prev[2]를 유지합니다.

Dijkstra-4
아직 방문하지 않은 vertex 중 가장 가까운 vertex는 4입니다.
visited[4]=true;를 실행합니다.
연결된 vertex는 2와 5가 있네요. 거리를 비교해 보면
2: 5>2+2 ⇒ dist[2]=4; prev[2]=4;
5: MAX>2+1 ⇒ dist[5]=3; prev[5]=4;
이렇게 진행됩니다.

Dijkstra-5
아직 방문하지 않은 vertex 중 가장 가까운 vertex는 5입니다.
visited[5]=true;를 실행합니다.
5번 vertex에는 연결된 vertex가 없네요.(2와 4는 역방향입니다.)

Dijkstra-2
아직 방문하지 않은 vertex 중 가장 가까운 vertex는 2입니다.
visited[2]=true;를 실행합니다.
나머지 vertex를 이미 모두 방문하였으므로 더 이상 업데이트할 것이 없습니다.

그 다음 choose() 함수를 호출하면 -1 또는 이미 방문한 vertex를 반환합니다.
19행 if (u == -1 || getVisited(u) == true) break;에 의해 반복문을 탈출하게 됩니다.

5. ★출발 지점으로부터 도착 지점까지의 최단 경로 및 최단 거리 구하기

위의 다익스트라 알고리즘 소스코드를 실행하면 dist, visited, prev를 업데이트할 뿐 최단 경로가 눈에 바로 보이지는 않습니다. 그러나 우리가 궁금한 것은 출발 지점으로부터 도착 지점까지의 최단 경로와 최단 거리입니다. 이것을 구하기 위해서 저는 void Graph::shortestPath(int start, int dest, vector<int>* result) 함수를 만들었습니다.

//Graph.cpp 48~73
void Graph::shortestPath(int start, int dest, vector<int>* result) {
	dijkstra(start);

	stack<int> path;
	int curr = dest;

	while (curr != start && curr != -1) {
		path.push(curr);
		curr = getPrev(curr);
	}

	if (curr == start) {
		path.push(curr);
	}
	else {	//No path
		result->clear();
		return;
	}

	while (!path.empty()) {
		result->push_back(path.top());
		path.pop();
	}

	return;
}

[Line 3]
dijkstra(start);
먼저 3번 문단의 dijkstra 함수를 호출하여 다익스트라 알고리즘을 수행합니다. parameter에는 start를 넣습니다.

[Line 5]
stack<int> path;
stack을 하나 선언합니다. stack은 후입선출(LIFO) 자료 구조이죠.
다익스트라 알고리즘을 수행하고 나면 prev 배열을 이용하여 이전 vertex를 알 수 있으므로, 도착 지점(dest)에서부터 prev 배열을 타고 이전 vertex로 가면서 stack에 push한 다음, 그 stack의 원소들을 꺼내면 경로가 깔끔하게 나올 것입니다.

[Line 6]
int curr = dest;
현재 위치를 curr로 표현합니다.
초기 currdest(도착 지점)입니다.

[Line 8~11]
curr != start && curr != -1이면 currpath에 push하고 curr에는 prev 배열을 이용하여 이전 vertex를 대입합니다. 이것을 반복합니다.

[Line 13~15]
반복문을 탈출했을 때 curr == start라면 currpath에 push합니다.

[Line 16~19]
반복문을 탈출했을 때 curr == -1이라면 경로가 없는 것이므로 result를 clear하고 return합니다.

[Line 21~24]
path가 빌 때까지 resultpath.top()를 삽입하고 path를 pop하는 것을 반복합니다.

참고로 console 출력은 Manager.cpp에서 구현했습니다.

//Manager.cpp Line 117~138
void Manager::shortestPath(int start, int end) {
	vector<int> path;
	int dist = 0;	//distance

	if (graph == nullptr) {
		cout << "Load graph first." << endl;
	}
	else {
		graph->shortestPath(start, end, &path);

		if (path.empty() || graph->getDistance(end) >= MAX) {
			cout << "X" << endl;	//can't go from start to end
		}
		else {
			for (int i = 0; i < path.size(); i++) {
				cout << path[i] << ' ';
			}

			cout << "(" << graph->getDistance(end) << ")" << endl;
		}
	}
}

[Line 3]
vector<int> path;
경로를 저장할 vector입니다. Graph.cpp 48~73의 result입니다.

[Line 10]
graph->shortestPath(start, dest, &path);
Graph.cpp 48~73의 함수를 호출합니다.

[Line 12~21]
path의 원소들을 출력합니다.

6. 나머지는 GitHub repository를 참고하세요.

이 글에서 설명하지 않은 부분(파일 입력 구현, arraysinit, choose 등)은 제가 GitHub에 올려 둔 소스코드(https://github.com/sooseongcom/Dijkstra)를 참고하시기 바랍니다.
특히 GitHub에 올려 둔 소스코드를 빌드하면 아래와 같은 명령어를 사용할 수 있으니 참고하시기 바랍니다.

  • load <filepath>: 그래프 파일(.txt)을 불러옵니다.
  • print: 그래프를 출력합니다.
  • shortestPath <start vertex> <destination vertex>: <start vertex>부터 <destination vertex>까지 최단 경로를 탐색합니다.

콘솔 예시
위 이미지는 사용 예시입니다.

7. 글 마무리

제 글을 읽어 주셔서 감사합니다. 다음에 만나요!

8. 참고 자료

1) KWiOS. 2022. “최단경로 - 다익스트라 알고리즘”, KWiOS0101. (2026. 02. 25. 방문). https://kwios0101.tistory.com/71