Rookiss님의 [c#과 유니티로 만드는 mmorpg 게임 개발 시리즈] part2 : 자료구조와 알고리즘 강의 내용을 정리했습니다.
Rookiss님의 [c++과 유니티로 만드는 mmorpg 게임 개발 시리즈] part3 : 자료구조와 알고리즘 강의 내용을 정리했습니다.
DFS
개념
- 깊이 우선 탐색 (Depth First Search)
- 더 이상 정점을 찾지 못할 때까지 정점을 타고 들어가고, 더이상 찾을 정점이 없으면 이전 위치로 복귀해서 또다른 정점을 찾는다.
- 재귀로 구현 가능하다.
리스트를 이용한 구현
List<int>[] nodes = new List<int>[]
{
new List<int>() { 1, 3},
new List<int>() { 0, 2, 3},
new List<int>() { 1 },
new List<int>() { 0, 1},
new List<int>() { 5 },
new List<int>() { 4 },
};
bool[] visited = new bool[6];
public void DFSByList(int now)
{
Console.WriteLine(now);
visited[now] = true; // 1) 우선 now부터 방문하고.
foreach (int next in nodes[now]) // 연결되어 있는 정점이 아니면 패스.
{
// 방문한 정점이면 패스.
if (visited[next])
{
continue;
}
DFSByList(next);
}
}
행렬을 이용한 구현
int[,] nodes = new int[6, 6]
{
{0, 1, 0, 1, 0, 0 },
{1, 0, 1, 1, 0, 0 },
{0, 1, 0, 0, 0, 0 },
{1, 1, 0, 0, 0, 0 },
{0, 0, 0, 0, 0, 1 },
{0, 0, 0, 0, 1, 0 },
};
bool[] visited = new bool[6];
// 1)우선 now 부터 방문하고
// 2)now와 연결된 정점들을 하나씩 확인해서, 아직 미발견 상태라면 방문한다.
public void DFSByMatrix(int now)
{
Console.WriteLine(now);
visited[now] = true; // 1) 우선 now부터 방문하고.
for(int next = 0; next < 6; next++)
{
// 연결되어 있는 정점이 아니면 패스.
if(nodes[now, next] == 0)
{
continue;
}
// 방문한 정점이면 패스.
if(visited[next])
{
continue;
}
DFSByMatrix(next);
}
}
구현시 주의할 점
- 정점이 모두 이어진 경우가 아니라면 dfs 탐색을 1회만으로 불가능 한 경우가 생긴다.
public void SearchAll()
{
visited = new bool[6];
for(int now = 0; now < 6; now++)
{
if(visited[now] == false)
{
DFSByMatrix(now);
}
}
}
BFS
개념
- 너비 우선 탐색 (Breadth First Search)
- 연결된 정점 정보를 저장하고 저장된 순서대로 꺼내서 다음 탐색을 시작한다.
- 순서대로 정점 정보를 사용하기 때문에 queue가 사용된다.
- 주로 길찾기 알고리즘에 사용된다.
리스트를 이용한 구현
class Graph
{
List<int>[] nodes = new List<int>[]
{
new List<int>() { 1, 3},
new List<int>() { 0, 2, 3},
new List<int>() { 1 },
new List<int>() { 0, 1, 4},
new List<int>() { 3, 5 },
new List<int>() { 4 },
};
public void BFSByList(int start)
{
bool[] found = new bool[6];
Queue<int> q = new Queue<int>();
q.Enqueue(start);
found[start] = true;
while (q.Count > 0)
{
int now = q.Dequeue();
Console.WriteLine(now);
// 인접하지 않으면 패스.
foreach (int next in nodes[now])
{
// 이미 발견 했으면 스킵.
if (found[next])
{
continue;
}
q.Enqueue(next);
found[next] = true;
}
}
}
}
행렬을 이용한 구현
class Graph
{
int[,] nodes = new int[6, 6]
{
{0, 1, 0, 1, 0, 0 },
{1, 0, 1, 1, 0, 0 },
{0, 1, 0, 0, 0, 0 },
{1, 1, 0, 0, 1, 0 },
{0, 0, 0, 1, 0, 1 },
{0, 0, 0, 0, 1, 0 },
};
public void BFSByMatrix(int start)
{
bool[] found = new bool[6];
Queue<int> q = new Queue<int>();
q.Enqueue(start);
found[start] = true;
while(q.Count > 0)
{
int now = q.Dequeue();
Console.WriteLine(now);
for(int next = 0; next < 6; next++)
{
// 인접하지 않으면 패스.
if(nodes[now, next] == 0)
{
continue;
}
// 이미 발견 했으면 스킵.
if(found[next])
{
continue;
}
q.Enqueue(next);
found[next] = true;
}
}
}
public void BFSByList(int start)
{
bool[] found = new bool[6];
Queue<int> q = new Queue<int>();
q.Enqueue(start);
found[start] = true;
while (q.Count > 0)
{
int now = q.Dequeue();
Console.WriteLine(now);
// 인접하지 않으면 패스.
foreach (int next in adj2[now])
{
// 이미 발견 했으면 스킵.
if (found[next])
{
continue;
}
q.Enqueue(next);
found[next] = true;
}
}
}
}
DFS vs BFS
- dfs는 발견과 동시에 방문한다. 다른 루트에 의해서 발견되었다고 해도 내가 먼저 방문하면 장땡.
- bfs는 발견된 정보는 우선 queue에 저장하고 queue 정보를 토대로 순차적으로 방문한다.