노드와 그 노드를 연결하는 간선을 하나로 모아 놓은 자료 구조
트리는 그래프의 일종이다. 하지만 그래프는 정점마다 간선이 존재하지 않을 수 있으며, 루트노트/자식노드와 같은 개념이 없다.
실생활에서 지하철 노선도 최단경로, 도로 등에 사용되고 있다.

두 정점을 연결하는 간선에 방향이 없는 그래프

두 정점을 연결하는 간선에 방향이 존재하는 그래프
간선이 가리키는 방향으로만 이동 가능

두 정점을 이동할때 비용이 드는 그래프

모든 정점이 간선으로 연결된 그래프

무방향 그래프에서, 연결 그래프가 아닌 그래프
인접 행렬이란 그래프의 정점을 2차원 배열로 만든 것이다.
직접 연결되어 있다면 1, 아니면 0을 저장

인접 리스트는 그래프의 노드를 리스트로 표현한 것이다. 주로 정점의 리스트 배열을 만들어서 관계를 설정한다.

DFS는 깊이 우선 탐색이라고 불리며 그 이유는 그래프의 시작점에서 다음 브랜치로 넘어가기 전에, 해당 브랜치를 모두 탐색하기 때문이다.

스택을 활용한 DFS의 동작 과정
1. 시작점인 1번 노드를 스택에 넣고 방문처리를 한다.
2. 스택 최상단 노드(1번)와 미방문한 노드 중 가장 번호가 낮은 2번 넣고 방문처리
3. 스택 최상단 노드(2번)와 미방문한 노드(7번)를 스택에 넣고 방문처리
4. 스택 최상단 노드(7번)와 미방문한 노드 중 가장 번호가 낮은 6번 넣고 방문처리
5. 스택 최상단 노드(6번)와 미방문한 노드가 없을때는 추출(pop)
6. 스택 최상단 노드(7번)와 미방문한 노드(8번)를 스택에 넣고 방문처리
7. 이와같은 메커니즘으로 스택에 아무것도 없을때까지 반복
구현
import java.util.Stack;
public class Main {
static boolean[] vistied = new boolean[9];
static int[][] graph = {{}, {2,3,8}, {1, 7}, {1, 4, 5}, {3, 5}, {3,4}, {7}, {2, 6, 8}, {1,7}};
static Stack<Integer> stack = new Stack<>();
public static void main(String[] args) {
stack.push(1);
vistied[1] = true;
while(!stack.isEmpty()) {
int nodeIndex = stack.pop();
System.out.print(nodeIndex + " -> ");
for (int LinkedNode : graph[nodeIndex]) {
if(!vistied[LinkedNode]) {
stack.push(LinkedNode);
vistied[LinkedNode] = true;
}
}
}
}
}
재귀함수를 활용
재귀 함수란 자기 자신을 다시 호출하는 함수를 의미
만약 종료조건을 제대로 명시하지 않으면, 함수가 무한이 호출되기 때문에 종료조건이 있어야한다.
이러한 특성때문에 DFS를 구현하는데 재귀함수를 쓴다.
public class Main {
static boolean[] vistied = new boolean[9];
static int[][] graph = {{}, {2,3,8}, {1, 7}, {1, 4, 5}, {3, 5}, {3,4}, {7}, {2, 6, 8}, {1,7}};
public static void main(String[] args) {
dfs(1);
}
static void dfs(int nodeIndex) {
vistied[nodeIndex] = true;
System.out.print(nodeIndex + " -> ");
for (int node : graph[nodeIndex]) {
// 인접한 노드가 방문한 적이 없다면 DFS 수행
if(!vistied[node]) {
dfs(node);
}
}
}
}
루트 노드(혹은 임의의 다른 노드)에서부터 시작하여 인접한 노드를 먼저 탐색해 나가는 방법이다.
또한 BFS는 그래프에서 최단 경로를 찾는 정점 기반 알고리즘으로 유명하다.
BFS는 자료구조 큐(Queue)를 사용하여 구현 할 수 있다.
특징
큐를 이용하여 구현
import java.util.LinkedList;
import java.util.Queue;
public class Main {
static boolean[] vistied = new boolean[9];
static int[][] graph = {{}, {2,3,8}, {1, 7}, {1, 4, 5}, {3, 5}, {3,4}, {7}, {2, 6, 8}, {1,7}};
public static void main(String[] args) {
System.out.println(bfs(1, graph, vistied));
}
static String bfs(int start, int[][] graph, boolean[] visited) {
StringBuilder sb = new StringBuilder();
Queue<Integer> q = new LinkedList<>();
q.offer(start);
visited[start] = true;
while(!q.isEmpty()) {
int nodeIndex = q.poll();
sb.append(nodeIndex + " -> ");
for(int i=0; i<graph[nodeIndex].length; i++) {
int temp = graph[nodeIndex][i];
if(!visited[temp]) {
visited[temp] = true;
q.offer(temp);
}
}
}
return sb.toString() ;
}
}