그래프는 이 블로그에서 가져온 그림을 참고했다.
1. 재귀 함수를 이용한 방식
#include <iostream>
#include <vector>
#include <time.h> // To measure execution time
#define SIZE 9
using namespace std;
void DFS(vector<int> _graph[], bool _visit[], int _startIndex)
{
if (_visit[_startIndex])
return;
_visit[_startIndex] = true;
cout << _startIndex;
for (int i = 0; i < _graph[_startIndex].size(); ++i)
{
// Recursive
DFS(_graph, _visit, _graph[_startIndex][i]);
}
}
void LinkTwoNodes(vector<int>_graph[], int _a, int _b)
{
_graph[_a].push_back(_b);
_graph[_b].push_back(_a);
}
void MakeGraph(vector<int> _graph[])
{
LinkTwoNodes(_graph, 1, 2);
LinkTwoNodes(_graph, 2, 3);
LinkTwoNodes(_graph, 1, 4);
LinkTwoNodes(_graph, 4, 5);
LinkTwoNodes(_graph, 5, 6);
LinkTwoNodes(_graph, 4, 7);
LinkTwoNodes(_graph, 1, 8);
LinkTwoNodes(_graph, 8, 9);
}
int main()
{
time_t startTime = clock();
vector<int> graph[SIZE + 1];
bool visit[SIZE + 1] = { false };
MakeGraph(graph);
DFS(graph, visit, 1);
time_t endTime = clock();
cout << "\nexecution time : " << endTime - startTime << endl;
return 0;
}
실행 시간은 53ms이다.
재귀 함수를 쓰는 경우 가독성이 좋지만 메모리를 많이 차지하고 성능이 반복문에 비해 느리다.
2. 스택을 이용한 방식
#include <iostream>
#include <stack>
#include <vector>
#include <time.h> // To measure execution time
#define SIZE 9
using namespace std;
void DFS(vector<int> _graph[], bool _visit[])
{
stack<int> dfsStack;
int currentIndex = 1;
dfsStack.push(currentIndex);
_visit[currentIndex] = true;
cout << currentIndex;
while (!dfsStack.empty())
{
currentIndex = dfsStack.top();
dfsStack.pop();
for (size_t i = 0; i < _graph[currentIndex].size(); ++i)
{
if (!_visit[_graph[currentIndex][i]])
{
dfsStack.push(currentIndex); // push again
currentIndex = _graph[currentIndex][i];
dfsStack.push(currentIndex);
_visit[currentIndex] = true;
cout << currentIndex;
break;
}
}
}
}
void LinkTwoNodes(vector<int>_graph[], int _a, int _b)
{
_graph[_a].push_back(_b);
_graph[_b].push_back(_a);
}
void MakeGraph(vector<int> _graph[])
{
LinkTwoNodes(_graph, 1, 2);
LinkTwoNodes(_graph, 2, 3);
LinkTwoNodes(_graph, 1, 4);
LinkTwoNodes(_graph, 4, 5);
LinkTwoNodes(_graph, 5, 6);
LinkTwoNodes(_graph, 4, 7);
LinkTwoNodes(_graph, 1, 8);
LinkTwoNodes(_graph, 8, 9);
}
int main()
{
time_t startTime = clock();
vector<int> graph[SIZE + 1];
bool visit[SIZE + 1] = { false };
MakeGraph(graph);
DFS(graph, visit);
time_t endTime = clock();
cout << "\nexecution time : " << endTime - startTime << endl;
return 0;
}
실행시간은 54ms이다.
스택을 사용하여 구현하는 경우 스택 오버플로우를 주의해야한다.
3. 시간 복잡도
V : 노드(정점)
E : 엣지(간선)
3.1. 그래프를 인접행렬 (이차원 배열)로 구성하는 경우
DFS가 각 정점(|V|)마다 호출되고 연결된 정점을 찾는데 |V|만큼의 시간이 걸린다.
따라서 O( |V|^2 )
3.2. 그래프를 인접리스트 (벡터의 배열)로 구성하는 경우
DFS가 각 정점(|V|)마다, 각 간선(|E|)마다 호출된다.
따라서 O( |V|+|E| )
'C++' 카테고리의 다른 글
정적 바인딩, 동적 바인딩, 가상 함수 테이블 (0) | 2020.02.16 |
---|---|
BFS 구현 (큐) (0) | 2020.02.16 |
A* 알고리즘 설명 (0) | 2020.02.16 |
A* 알고리즘에서 어떤 휴리스틱 함수를 사용해야할까 (0) | 2020.02.16 |
NULL과 nullptr의 차이 (0) | 2020.02.04 |