이번 포스트로 아마 자료구조 포스트는 마무리 될 것이다. 물론, 고급 자료구조로 넘어가면 더 자세히 나갈 부분은 남았지만, 이는 그때그때 학습을 하게 되어 저장해야할 일이 생기면 추가 'cs공부' 포스트 내에 입력하도록 하겠다. 이번 포스트에서 다룰 주제는 '그래프'이다.
그래프 알고리즘은 수학자 '오일러'에 의해서 고안되었다. '쾨니히스베르크의 다리' 문제에서 고안되었다고 보면 된다.
이런 다리가 있을 때 왔던 길을 지나지 않고, 다 통과할 수 있는 방법을 찾는 유형의 문제인데 이 문제를 풀기 위해서는 그래프 알고리즘을 사용할 수 밖에 없다. (물론, 윗 그림에서의 답은 없다는 것을 알 수 있다.)
용어 정리를 먼저 해보도록 하겠다.
정점 (vertex) : 연결의 대상이 되는 개체, 위치
간선 (edge) : 정점 사이를 연결하는 선
간선에는 방향성이 있을 수도 있고, 없을 수도 있다.
- 무방향 그래프 (undirected graph) : 위 그림처럼 간선에 방향성이 없는 그래프를 말한다.
- 방향 그래프 (directed graph) or 다이그래프 (digraph) : 그래프에 방향성이 있는 그래프
가중치 그래프 ( Weight Graph) : 간선에 가중치를 둔 그래프
위 그래프로, 최단거리를 구하거나 시간을 최소하게 갈 수 있는 알고리즘을 구할 수 있다. 거리나 시간을 가중치로 계산하여 문제를 풀 수 있기 때문이다.
부분 그래프 ( Sub Graph) : 원 그래프의 일부 정점 및 간선으로 이뤄진 그래프
그동안 잠시 자료구조에서 구조를 표현하는데 초점을 둬서 ADT를 정의를 안했었는데, 그래프는 ADT 가 존재한다.
그래프의 초기화를 담당하며 두번째 인자로 정점의 수를 전달한다.
void GraphInit(UALGraph * pg, int nv);
그래프 초기화에 할당한 리소스를 반환하는 기능
void GraphDestroy(UALGraph * pg);
매개변수 from V 와 to V 로 전달된 정점을 연결하는 간선을 추가함.
void ADDEdge(UALGraph * pg, int fromV, int toV);
그래프의 간선정보를 출력함.
void ShowGraphEdgeInfo(UALGraph * pg);
그래프를 구현하는 방법을 총 2가지를 학습해보았다.
1) 먼저 첫번째는 정방행렬로 하는 인접 행렬(adjacent matrix)기반 그래프이다. 정방행렬은 다음과 같다.
윗 그림을 보고 알 수 있는 정방행렬의 특징은 가로세로의 길이가 같은 행렬인 것이다. 즉, 정점의 개수가 n개일 때, nXn 의 '2차원 배열'을 만든 이후, 정점끼리 연결된 부분에는 1, 안 연결된 부분에는 0을 입력하여 그래프가 연결되어있는지 연결되어있지 않은지 여부를 확인하는 방법이다.
2) 두번째로는 연결리스트를 활용한 방법이다. 인접 리스트(adjacent list)기반 그래프이다. 정점에 연결된 정보를 리스트로 연결해서 담는 방법이라고 생각하면 된다.
: 그래프의 여러 갈래 길에서 한 길을 깊이 파고드는 탐색을 말한다. 그 이후 간선이 없으면 다시 돌아온다.
구현하는 방법에서는 스택과 배열을 사용한다.
: 자신에게 연결된 모든 정점에게 하나씩 값을 찾아가는 방식
(Breadth 뜻이 폭 인것과 같이 시작되는 정점부터 하나씩 폭을 넓혀 다 보고 넘어간다고 생각하면 된다.)
구현하는 방법에서는 배열은 똑같이 쓰이고, 여기서는 큐를 사용한다.
밑에 사진으로 BFS와 DFS 의 차이를 이해하면 좋을 것 같다. 혹시 이 포스트를 보고 학습하는 사람이 있다면 관련 알고리즘을 적용하는 문제들이 백준에 많이 있기에 풀어보는 것도 좋을 것이다.
최소 비용 신장 트리 (Minimum cost Spanning Tree: MST)에 관련해서도 알아보겠다. 그 전에 용어 하나 설명하고 진행하도록 하겠다. 경로(path)란, 두 개의 정점을 잇는 간선을 순서대로 나열한 것을 말한다. 단순 경로(simple path)는 동일한 간선을 중복하여 포함하지 않는 경로를 말하고, 사이클(cycle)은 단순 경로이면서, 시작과 끝이 같은 경로를 말한다.
MST는 그래프의 모든 정점이 간선에 의해 하나로 연결되어 있는 것을 말한다. 그래프 내에 사이클이 형성이 되어있지 않다.
최소비용신장트리를 구성하는데 사용하는 알고리즘을 하나 소개해보고 이 포스트를 마무리해보도록 하겠다. 물론, 지금 설명할 알고리즘을 제외하고도 많은 알고리즘이 존재한다. 대표적인 알고리즘은 크루스칼(Kruskal) 알고리즘이다.
1) 가중치를 오름차순하는 방법
2) 가중치를 내림차순하는 방법
(밑에 사진 첫 번째는 가중치 오름차순, 두번 째는 가중치 내림차순 그래프라고 생각하면 될 것이다. )
이렇게 자료구조를 약 13챕터로 학습을 마무리하겠다. 물론, 이번에 다룬 자료구조들은 기본이 되는 자료구조이다. 이 자료구조를 활용해서 사용자가 필요에 따라 또 다른 자료구조를 만들 수도 있고, 우리는 이를 만들지는 않더라도 만들어진 자료구조가 있다면 이해를 해야하기 때문에 자료구조에 대한 학습이 꼭 필요하다고 생각한다. CS 챕터는 2-2 컴퓨터 구조에 대한 학습을 하면서 다른 부분으로 다시 올리도록 하겠다.