|
| 1 | +## 1. 트리(Tree)란? |
| 2 | +계층적 관계를 표현하는 비선형 자료구조로, 노드들과 노드들을 연결하는 간선들로 구성됩니다. |
| 3 | + |
| 4 | +### 1.1 기본 용어 |
| 5 | +- 노드(Node): 트리의 기본 요소 |
| 6 | +- 루트(Root): 트리의 최상위 노드 |
| 7 | +- 간선(Edge): 노드를 연결하는 선 |
| 8 | +- 부모 노드: 상위 노드 |
| 9 | +- 자식 노드: 하위 노드 |
| 10 | +- 리프 노드: 자식이 없는 노드 |
| 11 | +- 깊이(Depth): 루트에서 특정 노드까지의 거리 |
| 12 | +- 높이(Height): 트리의 최대 깊이 |
| 13 | + |
| 14 | +## 2. 이진 트리 구현 |
| 15 | + |
| 16 | +### 2.1 노드 클래스 |
| 17 | +```javascript |
| 18 | +class Node { |
| 19 | + constructor(value) { |
| 20 | + this.value = value; |
| 21 | + this.left = null; |
| 22 | + this.right = null; |
| 23 | + } |
| 24 | +} |
| 25 | +``` |
| 26 | + |
| 27 | +### 2.2 이진 트리 클래스 |
| 28 | +```javascript |
| 29 | +class BinaryTree { |
| 30 | + constructor() { |
| 31 | + this.root = null; |
| 32 | + } |
| 33 | + |
| 34 | + // 노드 삽입 |
| 35 | + insert(value) { |
| 36 | + const newNode = new Node(value); |
| 37 | + |
| 38 | + if (!this.root) { |
| 39 | + this.root = newNode; |
| 40 | + return this; |
| 41 | + } |
| 42 | + |
| 43 | + let current = this.root; |
| 44 | + while(true) { |
| 45 | + if (value < current.value) { |
| 46 | + if (!current.left) { |
| 47 | + current.left = newNode; |
| 48 | + return this; |
| 49 | + } |
| 50 | + current = current.left; |
| 51 | + } else { |
| 52 | + if (!current.right) { |
| 53 | + current.right = newNode; |
| 54 | + return this; |
| 55 | + } |
| 56 | + current = current.right; |
| 57 | + } |
| 58 | + } |
| 59 | + } |
| 60 | +} |
| 61 | +``` |
| 62 | + |
| 63 | +## 3. 트리 순회 방법 |
| 64 | + |
| 65 | +### 3.1 전위 순회(Pre-order) |
| 66 | +```javascript |
| 67 | +preOrder(node = this.root, result = []) { |
| 68 | + if (node) { |
| 69 | + result.push(node.value); // 현재 노드 |
| 70 | + this.preOrder(node.left, result); // 왼쪽 서브트리 |
| 71 | + this.preOrder(node.right, result); // 오른쪽 서브트리 |
| 72 | + } |
| 73 | + return result; |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +### 3.2 중위 순회(In-order) |
| 78 | +```javascript |
| 79 | +inOrder(node = this.root, result = []) { |
| 80 | + if (node) { |
| 81 | + this.inOrder(node.left, result); // 왼쪽 서브트리 |
| 82 | + result.push(node.value); // 현재 노드 |
| 83 | + this.inOrder(node.right, result); // 오른쪽 서브트리 |
| 84 | + } |
| 85 | + return result; |
| 86 | +} |
| 87 | +``` |
| 88 | + |
| 89 | +### 3.3 후위 순회(Post-order) |
| 90 | +```javascript |
| 91 | +postOrder(node = this.root, result = []) { |
| 92 | + if (node) { |
| 93 | + this.postOrder(node.left, result); // 왼쪽 서브트리 |
| 94 | + this.postOrder(node.right, result); // 오른쪽 서브트리 |
| 95 | + result.push(node.value); // 현재 노드 |
| 96 | + } |
| 97 | + return result; |
| 98 | +} |
| 99 | +``` |
| 100 | + |
| 101 | +### 3.4 레벨 순회(Level-order) |
| 102 | +```javascript |
| 103 | +levelOrder() { |
| 104 | + if (!this.root) return []; |
| 105 | + |
| 106 | + const result = []; |
| 107 | + const queue = [this.root]; |
| 108 | + |
| 109 | + while (queue.length) { |
| 110 | + const node = queue.shift(); |
| 111 | + result.push(node.value); |
| 112 | + |
| 113 | + if (node.left) queue.push(node.left); |
| 114 | + if (node.right) queue.push(node.right); |
| 115 | + } |
| 116 | + |
| 117 | + return result; |
| 118 | +} |
| 119 | +``` |
| 120 | + |
| 121 | +## 4. 이진 검색 트리(BST) |
| 122 | + |
| 123 | +### 4.1 기본 구현 |
| 124 | +```javascript |
| 125 | +class BST { |
| 126 | + constructor() { |
| 127 | + this.root = null; |
| 128 | + } |
| 129 | + |
| 130 | + // 노드 삽입 |
| 131 | + insert(value) { |
| 132 | + const newNode = new Node(value); |
| 133 | + |
| 134 | + if (!this.root) { |
| 135 | + this.root = newNode; |
| 136 | + return this; |
| 137 | + } |
| 138 | + |
| 139 | + let current = this.root; |
| 140 | + while (true) { |
| 141 | + if (value === current.value) return undefined; |
| 142 | + if (value < current.value) { |
| 143 | + if (!current.left) { |
| 144 | + current.left = newNode; |
| 145 | + return this; |
| 146 | + } |
| 147 | + current = current.left; |
| 148 | + } else { |
| 149 | + if (!current.right) { |
| 150 | + current.right = newNode; |
| 151 | + return this; |
| 152 | + } |
| 153 | + current = current.right; |
| 154 | + } |
| 155 | + } |
| 156 | + } |
| 157 | + |
| 158 | + // 값 찾기 |
| 159 | + find(value) { |
| 160 | + if (!this.root) return false; |
| 161 | + |
| 162 | + let current = this.root; |
| 163 | + while (current) { |
| 164 | + if (value === current.value) return true; |
| 165 | + if (value < current.value) { |
| 166 | + current = current.left; |
| 167 | + } else { |
| 168 | + current = current.right; |
| 169 | + } |
| 170 | + } |
| 171 | + return false; |
| 172 | + } |
| 173 | +} |
| 174 | +``` |
| 175 | + |
| 176 | +## 5. 성능 고려사항 |
| 177 | + |
| 178 | +### 5.1 시간 복잡도 |
| 179 | +- 삽입: O(log n) - 균형 트리의 경우 |
| 180 | +- 검색: O(log n) - 균형 트리의 경우 |
| 181 | +- 삭제: O(log n) - 균형 트리의 경우 |
| 182 | +- 최악의 경우: O(n) - 불균형 트리의 경우 |
| 183 | + |
| 184 | +### 5.2 공간 복잡도 |
| 185 | +- O(n) - n은 노드의 수 |
| 186 | + |
| 187 | +## 6. 트리 관련 알고리즘 |
| 188 | + |
| 189 | +### 6.1 최소 공통 조상(LCA) 찾기 |
| 190 | +```javascript |
| 191 | +function findLCA(root, n1, n2) { |
| 192 | + if (!root) return null; |
| 193 | + |
| 194 | + if (root.value === n1 || root.value === n2) { |
| 195 | + return root; |
| 196 | + } |
| 197 | + |
| 198 | + const left = findLCA(root.left, n1, n2); |
| 199 | + const right = findLCA(root.right, n1, n2); |
| 200 | + |
| 201 | + if (left && right) return root; |
| 202 | + |
| 203 | + return left ? left : right; |
| 204 | +} |
| 205 | +``` |
| 206 | + |
| 207 | +### 6.2 트리의 깊이 찾기 |
| 208 | +```javascript |
| 209 | +function findDepth(root) { |
| 210 | + if (!root) return 0; |
| 211 | + return Math.max(findDepth(root.left), findDepth(root.right)) + 1; |
| 212 | +} |
| 213 | +``` |
0 commit comments