VioletaBabel
그래프 본문
트리는 사이클이 없는 연결 그래프이다.
그래프는 노드와 노드를 연결하는 간선을 하나로 모은 것이다.
사이클이 없는 그래프를 비순환 그래프라고 한다.
모든 정점 간에 경로가 존재하는 그래프를 연결 그래프라고 한다.
--
인접 리스트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | #include <cstdio> #include <algorithm> using namespace std; struct node { node *next, *prev; int num; }; node *head[9], *foot; void init(); int main() { node *now, *newnode; init(); int n, x, y, z; printf("1부터 9까지의 거점 사이에 존재하는 경로를 기록한다.\n경로의 갯수는? "); for (scanf("%d", &n); n--;) { printf("경로의 출발 거점과 도착 거점을 적어주세요 : "); scanf("%d %d", &x, &y); printf("경로가 일방통행이면 1, 아니면 2를 입력해주세요 : "); scanf("%d", &z); while(z--) { now = head[x-1]; while (1) { if (now->next->num == 0) { newnode = new node; newnode->prev = now; newnode->next = foot; now->next = newnode; newnode->num = y; break; } else { if (now->next->num == y) break; else now = now->next; } } swap(x, y); } } for (int i = 0; i < 9; ++i) { printf("%d : ", i + 1); now = head[i]; while (1) { if (now->next->num != 0) { printf("%d ", now->next->num); now = now->next; } else { printf("\n"); break; } } } } void init() { foot = new node; foot->num = 0; foot->next = foot; for (int i = 0; i < 9; ++i) { head[i] = new node; head[i]->next = foot; head[i]->prev = head[i]; head[i]->num = 0; } } | cs |
--
인접 행렬
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #include <cstdio> int main() { bool num[9][9]; for (int i = 0; i < 9; ++i) for (int j = 0; j < 9; ++j) num[i][j] = 0; int n, x, y, z; printf("1부터 9까지의 거점 사이에 존재하는 경로를 기록한다.\n경로의 갯수는? "); for (scanf("%d", &n); n--;) { printf("경로의 출발 거점과 도착 거점을 적어주세요 : "); scanf("%d %d", &x, &y); printf("경로가 일방통행이면 1, 아니면 2를 입력해주세요 : "); scanf("%d", &z); if (z == 1) num[x - 1][y - 1] = 1; else if (z == 2) { num[x - 1][y - 1] = 1; num[y - 1][x - 1] = 1; } } for (int i = 0; i < 9; ++i) { printf("%d : ", i + 1); for(int j = 0; j < 9; ++j) if (num[i][j]) printf("%d ", j + 1); printf("\n"); } } |
--
그래프 탐색
깊이 우선 탐색(DFS) : 각 분기를 완벽하게 탐색 후 다른 분기를 탐색
너비 우선 탐색(BFS) : 루트 노드의 인접한 노드들 부터 탐색 후, 그 노드들의 인접한 노드를 이어가듯 탐색
--
DFS
DFS를 재귀로 하면, 저번 글에 작성했던 전위, 중위, 후위 순회와 같다고 보면 됨.
BFS는 큐를 이용
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #include <cstdio> #include <queue> using namespace std; void dfs(int nx); void bfs(int nx); bool num1[9][9], num2[9][9]; queue<int> q; int main() { for (int i = 0; i < 9; ++i) for (int j = 0; j < 9; ++j) { num1[i][j] = 0; num2[i][j] = 0; } int n, x, y; printf("1부터 9까지의 거점 사이에 존재하는 경로를 기록한다.\n경로의 갯수는? "); for (scanf("%d", &n); n--;) { printf("경로의 출발 거점과 도착 거점을 적어주세요 : "); scanf("%d %d", &x, &y); num1[x-1][y-1] = 1; num1[y-1][x-1] = 1; num2[x-1][y-1] = 1; num2[y-1][x-1] = 1; } printf("\n탐색을 시작할 경로의 시작점을 적어주세요 : "); scanf("%d", &n); printf("\n\ndfs : "); dfs(n - 1); printf("\n\nbfs : "); bfs(n - 1); printf("\n"); } void dfs(int nx) { printf("%d ", nx + 1); for (int i = 0; i < 9; ++i) num1[i][nx] = 0; for (int i = 0; i < 9; ++i) if (num1[nx][i]) dfs(i); } void bfs(int nx) { int a; q.push(nx); for (int i = 0; i < 9; ++i) num2[i][nx] = 0; while (!q.empty()) { a = q.front(); q.pop(); printf("%d ", a + 1); for (int i = 0; i < 9; ++i) if (num2[a][i]) { q.push(i); for (int j = 0; j < 9; ++j) num2[j][i] = 0; } } } | cs |
--
양방향 탐색
이건 코딩까진 안하겠음
너비 우선 탐색 시 출발지와 도착지에서 동시에 너비 탐색을 하면 두 탐색 지점이 충돌하는 경우가 최단 경로가 됨.
4단계 떨어진 곳이면 출발지에서 2단계, 도착지에서 2단계로 2단계만에 찾을 수 있음.
그런 식으로 같은 단계 깊이동안 찾을 경로의 길이가 늘어난다고 표현되어 있음.
Comments