VioletaBabel

그래프 본문

기본개념/알고리즘공부
그래프
Beabletoet 2017. 9. 9. 22:10

트리는 사이클이 없는 연결 그래프이다.


그래프는 노드와 노드를 연결하는 간선을 하나로 모은 것이다.


사이클이 없는 그래프를 비순환 그래프라고 한다.


모든 정점 간에 경로가 존재하는 그래프를 연결 그래프라고 한다.



--

인접 리스트


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");
    }
}

cs



--
그래프 탐색

깊이 우선 탐색(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단계만에 찾을 수 있음.

그런 식으로 같은 단계 깊이동안 찾을 경로의 길이가 늘어난다고 표현되어 있음.



'기본개념 > 알고리즘공부' 카테고리의 다른 글

객체 지향 설계  (0) 2017.09.13
비트 조작  (0) 2017.09.11
트리  (0) 2017.09.08
  (0) 2017.09.08
스택  (0) 2017.09.08
Comments