비선형 구조의 여러 구조 중 단방향의 한 구조, 그래프인데 단방향인 거임, 하나의 뿌리로부터 가지가 사방으로 뻗은 형태가 나무와 닮아 있음
효율적인 탐색을 위해 고민하여 나온 것이 이진 트리다!
자식 노드가 최대 두 개인 노드들로 구성된 트리, 두 개의 자식 노드는 왼쪽 자식 노드와 오른쪽 자식 노드로 나눔
자료의 삽입, 삭제 방법에 따라 정 이진 트리(Full binary tree), 완전 이진 트리(Complete binary tree), 포화 이진 트리(Perfect binary tree)로 나눈다!
Binary Search Tree, 이진 탐색(binary search)과 연결 리스트(linked list)를 결합한 이진트리
- 각 노드에 중복되지 않는 키(Key)가 있음.
- 루트노드의 왼쪽 서브 트리는 해당 노드의 키보다 작은 키를 갖는 노드들로 이루어져 있음.
- 루트노드의 오른쪽 서브 트리는 해당 노드의 키보다 큰 키를 갖는 노드들로 이루어져 있음.
- 좌우 서브트리도 모두 이진 탐색 트리여야 함.
단점: 균형 잡힌 트리가 아닐 때, 입력되는 값의 순서에 따라 한쪽으로 노드들이 몰리게 될 수 있음, 해결하고 싶다면 삽입과 삭제마다 트리의 구조를 재조정하는 과정을 거치는 알고리즘을 추가해야한다!
즉, 모든 왼쪽 자식의 값이 루트나 부모보다 작고, 모든 오른쪽 자식의 값이 루트나 부모보다 큰 값을 가지는 특징을 가진다!
5라는 값을 찾고자 한다.
만약 3을 찾는다면 4번의 연산이 진행되었을 것. 즉! 트리 안의 값을 찾는다면 무조건 트리의 높이(h) 이하의 탐색
즉! 최대 h번의 연산 및 탐색이 진행 - 트리의 높이(h) 이하의 탐색, 시간복잡도는 O(h)!
특정 목적을 위해 트리의 모든 노드를 한 번씩 방문하는 것, 모든 노드를 방문하기 위해서 일정한 조건이 필요, 트리 구조를 유지보수하거나 특정 목적을 위해서도 순회 방법에 대한 정의는 필수적으로 필요
트리 순회는 크게 DFS(Depth-First Search)와 BFS(Breadth-First Search)로 나눌 수 있다.
지그재그 순회, 모리스 순회, 경계 순회, 대각선 순회 등이 있지만 가장 유명한 순회만 살펴보겠다.
레벨 순회(Level-order Traverse)라고도 하며, 같은 레벨의 노드들을 왼쪽에서 오른쪽으로 순회한다.
아래와 같은 방법을 요구할 때, 적합하다!
최단 경로 찾기
레벨 단위 처리가 필요한 경우
그래프의 연결 요소 탐색
상태 공간 탐색
동심원적 탐색이 필요한 경우
// 최단 경로 찾기 예시
function findShortestPath(graph, start, end) {
const queue = [[start, [start]]];
const visited = new Set([start]);
while (queue.length > 0) {
const [current, path] = queue.shift();
if (current === end) {
return path;
}
for (let neighbor of graph[current]) {
if (!visited.has(neighbor)) {
visited.add(neighbor);
queue.push([neighbor, [...path, neighbor]]);
}
}
}
return null; // 경로가 없는 경우
}
특성 | BFS (너비 우선 탐색) | DFS (깊이 우선 탐색) |
---|---|---|
탐색 방식 | 레벨 단위로 너비 우선 탐색 | 한 경로를 끝까지 탐색 후 백트래킹 |
자료구조 | 큐(Queue) 사용 | 스택(Stack) 또는 재귀 사용 |
메모리 | 큐에 동일 레벨의 모든 노드 저장으로 많은 메모리 필요 | 현재 경로의 노드만 저장하여 적은 메모리 사용 |
최적화 | 최단 경로 보장 (가중치가 없거나 동일한 경우) | 최단 경로 보장하지 않음 |
완전성 | 유한 그래프에서 해 존재시 반드시 찾음 | 무한 그래프에서도 해를 찾을 수 있음 |
적합한 경우 | • 최단 경로 찾기 • 레벨 단위 처리 • 인접 노드 탐색 • 상태 트리가 넓지만 얕은 경우 | • 경로 존재 여부 확인 • 사이클 탐지 • 위상 정렬 • 상태 트리가 깊고 좁은 경우 |
시간 복잡도 | O(V + E) - V는 정점, E는 간선 | O(V + E) - V는 정점, E는 간선 |
구현 복잡도 | 상대적으로 단순 | 재귀로 인해 상대적으로 복잡 |
방문 순서 | 시작점에서 가까운 순서대로 방문 | 한 방향으로 최대한 깊이 방문 |
백트래킹 | 불필요 | 필요 (이전 분기점으로 돌아가야 함) |
BFS 사용이 좋은 경우
DFS 사용이 좋은 경우