From a25948107a8b4db03fbe7428d3f1907dcde818b0 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:35:27 +0900 Subject: [PATCH 1/7] =?UTF-8?q?Tree=20traversal=20basic=20/=20=EA=B8=B0?= =?UTF-8?q?=EC=B4=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tree_traversal_basic/input.txt | 8 ++ .../Tree_traversal_basic/map_version.js | 50 +++++++++++ .../node_class_version.js | 84 +++++++++++++++++++ 3 files changed, 142 insertions(+) create mode 100644 bona1122/[week5]Tree/Tree_traversal_basic/input.txt create mode 100644 bona1122/[week5]Tree/Tree_traversal_basic/map_version.js create mode 100644 bona1122/[week5]Tree/Tree_traversal_basic/node_class_version.js diff --git a/bona1122/[week5]Tree/Tree_traversal_basic/input.txt b/bona1122/[week5]Tree/Tree_traversal_basic/input.txt new file mode 100644 index 0000000..e333156 --- /dev/null +++ b/bona1122/[week5]Tree/Tree_traversal_basic/input.txt @@ -0,0 +1,8 @@ +7 +A B C +B D . +C E F +E . . +F . G +D . . +G . . \ No newline at end of file diff --git a/bona1122/[week5]Tree/Tree_traversal_basic/map_version.js b/bona1122/[week5]Tree/Tree_traversal_basic/map_version.js new file mode 100644 index 0000000..3e727f8 --- /dev/null +++ b/bona1122/[week5]Tree/Tree_traversal_basic/map_version.js @@ -0,0 +1,50 @@ +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +const N = Number(input[0]) +const tree = new Map() + +// 트리 구성 +for (let i = 1; i <= N; i++) { + const [node, left, right] = input[i].split(" ") + tree.set(node, [left, right]) +} + +let result = "" + +// 전위 순회 +function preorder(node) { + if (node === ".") return + result += node // root + preorder(tree.get(node)[0]) // left 하위 트리 + preorder(tree.get(node)[1]) // right 하위 트리 +} + +// 중위 순회 +function inorder(node) { + if (node === ".") return + inorder(tree.get(node)[0]) // left 하위 트리 + result += node // root + inorder(tree.get(node)[1]) // right 하위 트리 +} + +// 후위 순회 +function postorder(node) { + if (node === ".") return + postorder(tree.get(node)[0]) // left 하위 트리 + postorder(tree.get(node)[1]) // right 하위 트리 + result += node // root +} + +// 결과 출력 +preorder("A") +result += "\n" +inorder("A") +result += "\n" +postorder("A") + +log(result) diff --git a/bona1122/[week5]Tree/Tree_traversal_basic/node_class_version.js b/bona1122/[week5]Tree/Tree_traversal_basic/node_class_version.js new file mode 100644 index 0000000..72eab8a --- /dev/null +++ b/bona1122/[week5]Tree/Tree_traversal_basic/node_class_version.js @@ -0,0 +1,84 @@ +// https://www.acmicpc.net/problem/1991 +// 이진 트리 입력되면, 전위순회/중위순회/후위순회 출력하기 + +const fs = require("fs") +const path = require("path") +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : path.join(__dirname, "input.txt") +let input = fs.readFileSync(filePath).toString().split("\n") +const log = console.log + +class Node { + constructor(value) { + this.value = value + this.left = null + this.right = null + } +} + +class BinaryTree { + constructor() { + this.root = null + } + + findNode(value, node = this.root) { + if (!node) return null + if (node.value === value) return node + return this.findNode(value, node.left) || this.findNode(value, node.right) + } + + insert(value, left, right) { + if (!this.root) { + this.root = new Node(value) + if (left !== ".") this.root.left = new Node(left) + if (right !== ".") this.root.right = new Node(right) + } else { + const node = this.findNode(value) + if (left !== ".") node.left = new Node(left) + if (right !== ".") node.right = new Node(right) + } + } +} + +const N = Number(input[0]) +const tree = new BinaryTree() +let result = "" + +for (let i = 1; i <= N; i++) { + const [node, left, right] = input[i].split(" ") + tree.insert(node, left, right) +} + +// 전위 순회 +function preorder(node) { + if (!node) return + result += node.value + preorder(node.left) + preorder(node.right) +} + +// 중위 순회 +function inorder(node) { + if (!node) return + inorder(node.left) + result += node.value + inorder(node.right) +} + +// 후위 순회 +function postorder(node) { + if (!node) return + postorder(node.left) + postorder(node.right) + result += node.value +} + +preorder(tree.root) +result += "\n" +inorder(tree.root) +result += "\n" +postorder(tree.root) + +log(result) From 34c9e3829b03f3909c61b13a5706933777e7d1f7 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:36:34 +0900 Subject: [PATCH 2/7] =?UTF-8?q?Complete=20binary=20tree=20/=20=EA=B8=B0?= =?UTF-8?q?=EC=B4=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Complete_binary_tree.js | 26 +++++++++++++++++++ .../Complete_binary_tree/input.txt | 2 ++ 2 files changed, 28 insertions(+) create mode 100644 bona1122/[week5]Tree/Complete_binary_tree/Complete_binary_tree.js create mode 100644 bona1122/[week5]Tree/Complete_binary_tree/input.txt diff --git a/bona1122/[week5]Tree/Complete_binary_tree/Complete_binary_tree.js b/bona1122/[week5]Tree/Complete_binary_tree/Complete_binary_tree.js new file mode 100644 index 0000000..33f22b5 --- /dev/null +++ b/bona1122/[week5]Tree/Complete_binary_tree/Complete_binary_tree.js @@ -0,0 +1,26 @@ +// https://www.acmicpc.net/problem/9934 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +// 상근이는 중위순회로 이진 트리를 순회한 결과를 가지고 있다. +// 각 레벨에 있는 빌딩 번호 구하기 +const k = +input[0] +const arr = input[1].split(" ").map(Number) +let result = Array.from({ length: k }, () => []) + +const dfs = (arr, depth) => { + if (arr.length < 1) return + + const mid = Math.floor(arr.length / 2) + result[depth].push(arr[mid]) + + dfs(arr.slice(0, mid), depth + 1) + dfs(arr.slice(mid + 1), depth + 1) +} + +dfs(arr, 0) +result.forEach((row) => log(row.join(" "))) diff --git a/bona1122/[week5]Tree/Complete_binary_tree/input.txt b/bona1122/[week5]Tree/Complete_binary_tree/input.txt new file mode 100644 index 0000000..dd601c1 --- /dev/null +++ b/bona1122/[week5]Tree/Complete_binary_tree/input.txt @@ -0,0 +1,2 @@ +3 +1 6 4 3 5 2 7 \ No newline at end of file From 623d66e5b1b8718f7307e344df96a46c97025199 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:37:32 +0900 Subject: [PATCH 3/7] =?UTF-8?q?Tree=20find=20parent=20/=20=EA=B8=B0?= =?UTF-8?q?=EC=B4=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tree_find_parent/Tree_find_parent.js | 36 +++++++++++++++++++ .../[week5]Tree/Tree_find_parent/input.txt | 7 ++++ 2 files changed, 43 insertions(+) create mode 100644 bona1122/[week5]Tree/Tree_find_parent/Tree_find_parent.js create mode 100644 bona1122/[week5]Tree/Tree_find_parent/input.txt diff --git a/bona1122/[week5]Tree/Tree_find_parent/Tree_find_parent.js b/bona1122/[week5]Tree/Tree_find_parent/Tree_find_parent.js new file mode 100644 index 0000000..ba0225c --- /dev/null +++ b/bona1122/[week5]Tree/Tree_find_parent/Tree_find_parent.js @@ -0,0 +1,36 @@ +// https://www.acmicpc.net/problem/11725 + +// 루트없는 트리 주어지면(트리루트 1), 2번노드부터 각 노드의 부모를 구하기 +// => 그래프 정보 저장하고, bfs로 탐색하면서 부모노드 찾기 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +const n = +input[0] +const graph = Array.from({ length: n + 1 }, () => []) +for (let i = 1; i < n; i++) { + let [v1, v2] = input[i].split(" ").map(Number) + graph[v1].push(v2) + graph[v2].push(v1) +} + +const visited = new Array(n + 1).fill(false) +const parent = new Array(n + 1).fill(0) + +const queue = [1] +visited[1] = true + +while (queue.length) { + let item = queue.shift() + + for (let v of graph[item]) { + if (visited[v]) continue + visited[v] = true + queue.push(v) + parent[v] = item + } +} +log(result.slice(2).join("\n")) diff --git a/bona1122/[week5]Tree/Tree_find_parent/input.txt b/bona1122/[week5]Tree/Tree_find_parent/input.txt new file mode 100644 index 0000000..1387927 --- /dev/null +++ b/bona1122/[week5]Tree/Tree_find_parent/input.txt @@ -0,0 +1,7 @@ +7 +1 6 +6 3 +3 5 +4 1 +2 4 +4 7 \ No newline at end of file From ad58a5f84ce77e6b6c5f80f2764a0a0e07786f34 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:38:13 +0900 Subject: [PATCH 4/7] =?UTF-8?q?Binary=5Ftree=5Fheight=20/=20=EA=B8=B0?= =?UTF-8?q?=EC=B4=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Binary_tree_height/Binary_tree_height.js | 50 +++++++++++++++++++ .../[week5]Tree/Binary_tree_height/input.txt | 3 ++ 2 files changed, 53 insertions(+) create mode 100644 bona1122/[week5]Tree/Binary_tree_height/Binary_tree_height.js create mode 100644 bona1122/[week5]Tree/Binary_tree_height/input.txt diff --git a/bona1122/[week5]Tree/Binary_tree_height/Binary_tree_height.js b/bona1122/[week5]Tree/Binary_tree_height/Binary_tree_height.js new file mode 100644 index 0000000..72dca4b --- /dev/null +++ b/bona1122/[week5]Tree/Binary_tree_height/Binary_tree_height.js @@ -0,0 +1,50 @@ +// https://www.acmicpc.net/problem/1068 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +// 노드 제거시, 노드와 노드의 모든 자손이 트리에서 제거됨 +// 노드를 지운 후, 트리의 리프노드 개수 구하기 +// => 부모노드 정보를 통해 그래프를 구성하고, bfs로 탐색하며 리프노드 개수 카운트 + +const n = +input[0] +const parents = input[1].split(" ").map(Number) +const remove = +input[2] +const graph = Array.from({ length: n }, () => []) +let root = -1 + +for (let i = 0; i < n; i++) { + const parent = parents[i] + if (parent === -1) { + root = i + } else { + graph[parent].push(i) + } +} + +let result = 0 +const queue = remove === root ? [] : [root] +const visited = new Array(n).fill(false) +visited[root] = true + +while (queue.length) { + let item = queue.shift() + let isLeaf = true + + for (let v of graph[item]) { + if (v !== remove) { + isLeaf = false + if (!visited[v]) { + visited[v] = true + queue.push(v) + } + } + } + + if (isLeaf) result++ +} + +log(result) diff --git a/bona1122/[week5]Tree/Binary_tree_height/input.txt b/bona1122/[week5]Tree/Binary_tree_height/input.txt new file mode 100644 index 0000000..399e5c8 --- /dev/null +++ b/bona1122/[week5]Tree/Binary_tree_height/input.txt @@ -0,0 +1,3 @@ +9 +-1 0 0 2 2 4 4 6 6 +4 \ No newline at end of file From e09fbed67a992fa0c51d6cf73838e7d41dad5cf5 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:39:13 +0900 Subject: [PATCH 5/7] =?UTF-8?q?Binary=20search=20tree=20/=20=EC=A4=91?= =?UTF-8?q?=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Binary_search_tree/Binary_search_tree.js | 29 +++++++++ .../Binary_search_tree_class_version.js | 62 +++++++++++++++++++ .../[week5]Tree/Binary_search_tree/input.txt | 9 +++ 3 files changed, 100 insertions(+) create mode 100644 bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree.js create mode 100644 bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree_class_version.js create mode 100644 bona1122/[week5]Tree/Binary_search_tree/input.txt diff --git a/bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree.js b/bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree.js new file mode 100644 index 0000000..9f30847 --- /dev/null +++ b/bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree.js @@ -0,0 +1,29 @@ +// https://www.acmicpc.net/problem/5639 +// 이진 검색트리의 전위 순회 경과가 주어지면, 후위순회 결과 구하기 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +const arr = input.map(Number) + +const postorder = (root, end) => { + if (root > end) return + + let right = end + 1 // 오른쪽 서브트리(루트보다 큰 요소들) 시작점 구하기 + for (let i = root + 1; i <= end; i++) { + if (arr[i] > arr[root]) { + right = i + break + } + } + + // 후위 순위로 출력 + postorder(root + 1, right - 1) + postorder(right, end) + log(arr[root]) +} + +postorder(0, arr.length - 1) diff --git a/bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree_class_version.js b/bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree_class_version.js new file mode 100644 index 0000000..8dd5205 --- /dev/null +++ b/bona1122/[week5]Tree/Binary_search_tree/Binary_search_tree_class_version.js @@ -0,0 +1,62 @@ +// https://www.acmicpc.net/problem/5639 +// 이진 검색트리의 전위 순회 경과가 주어지면, 후위순회 결과 구하기 + +// 핵심: BST의 전위순회 결과가 있기에, 순서대로 트리에 삽입하면 트리가 복원된다 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +const arr = input.map(Number) + +class Node { + constructor(value) { + this.value = value + this.left = null + this.right = null + } +} + +class BinarySearchTree { + constructor() { + this.root = null + } + + insert(value) { + if (!this.root) { + this.root = new Node(value) + return + } + + let current = this.root + while (true) { + if (value < current.value) { + if (!current.left) { + current.left = new Node(value) + break + } + current = current.left + } else { + if (!current.right) { + current.right = new Node(value) + break + } + current = current.right + } + } + } + + postorder(node = this.root) { + if (!node) return + + this.postorder(node.left) // 왼쪽 서브트리 순회 + this.postorder(node.right) // 오른쪽 서브트리 순회 + log(node.value) // 현재 노드 출력 + } +} + +const tree = new BinarySearchTree() +arr.forEach((item) => tree.insert(item)) +tree.postorder() diff --git a/bona1122/[week5]Tree/Binary_search_tree/input.txt b/bona1122/[week5]Tree/Binary_search_tree/input.txt new file mode 100644 index 0000000..e5d3e90 --- /dev/null +++ b/bona1122/[week5]Tree/Binary_search_tree/input.txt @@ -0,0 +1,9 @@ +50 +30 +24 +5 +28 +45 +98 +52 +60 \ No newline at end of file From bd92ea1081b2e39eb16df1e8927de80ef8969725 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:39:56 +0900 Subject: [PATCH 6/7] =?UTF-8?q?Tree=20and=20query=20/=20=EC=A4=91=EA=B8=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tree_and_query/Tree_and_query.js | 68 +++++++++++++++++++ bona1122/[week5]Tree/Tree_and_query/input.txt | 12 ++++ 2 files changed, 80 insertions(+) create mode 100644 bona1122/[week5]Tree/Tree_and_query/Tree_and_query.js create mode 100644 bona1122/[week5]Tree/Tree_and_query/input.txt diff --git a/bona1122/[week5]Tree/Tree_and_query/Tree_and_query.js b/bona1122/[week5]Tree/Tree_and_query/Tree_and_query.js new file mode 100644 index 0000000..3a0a69f --- /dev/null +++ b/bona1122/[week5]Tree/Tree_and_query/Tree_and_query.js @@ -0,0 +1,68 @@ +// https://www.acmicpc.net/problem/15681 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +// 가중치, 방향 없는 트리 +// 정점 U를 루트로 하는 서브트리에 속한 정점 수 출력하기 + +// 방법 1: 문제에서 주어진 힌트 처럼, 자식 배열을 활용 +const [N, R, Q] = input[0].split(" ").map(Number) + +const graph = Array.from({ length: N + 1 }, () => []) +const query = Array(Q) +const children = Array.from({ length: N + 1 }, () => []) +const size = Array(N + 1).fill(1) + +for (let i = 1; i <= N - 1; i++) { + let [u, v] = input[i].split(" ").map(Number) + graph[u].push(v) + graph[v].push(u) +} +let idx = 0 +for (let i = N; i < N + Q; i++) { + query[idx++] = +input[i] +} + +const makeTree = (cur, parent) => { + for (let next of graph[cur]) { + if (next !== parent) { + children[cur].push(next) + makeTree(next, cur) + } + } +} + +// 부모자식관계를 파악하기 위한 두 가지 방법 +// 1. 명시적으로 배열에 저장 -> makeTree 선행 필요 +const countSubtreeNodes = (cur) => { + for (let next of children[cur]) { + countSubtreeNodes(next) + size[cur] += size[next] + } +} +// 2. visited배열로 부모자식 파악 +const visited = Array(N + 1).fill(false) +const countSubtreeNodes2 = (node) => { + if (visited[node]) return size[node] + visited[node] = true // 방문 표시로 부모-자식 관계 파악 + + for (const next of graph[node]) { + if (!visited[next]) { + // 방문하지 않은 노드는 자식 + size[node] += countSubtreeNodes2(next) + } + } + return size[node] +} +/* + makeTree(R, 0) + countSubtreeNodes(R) + log(children) +*/ +countSubtreeNodes2(R) + +for (let q of query) log(size[q]) diff --git a/bona1122/[week5]Tree/Tree_and_query/input.txt b/bona1122/[week5]Tree/Tree_and_query/input.txt new file mode 100644 index 0000000..94052f7 --- /dev/null +++ b/bona1122/[week5]Tree/Tree_and_query/input.txt @@ -0,0 +1,12 @@ +9 5 3 +1 3 +4 3 +5 4 +5 6 +6 7 +2 3 +9 6 +6 8 +5 +4 +8 \ No newline at end of file From fa5494b49104bd54569cfbb613c3760fac13d8b2 Mon Sep 17 00:00:00 2001 From: bona1122 Date: Thu, 6 Feb 2025 20:40:43 +0900 Subject: [PATCH 7/7] =?UTF-8?q?Tree=5Ftraversal=20/=20=EC=8B=AC=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Tree_traversal/Tree_traversal.js | 40 +++++++++++++++++++ bona1122/[week5]Tree/Tree_traversal/input.txt | 3 ++ 2 files changed, 43 insertions(+) create mode 100644 bona1122/[week5]Tree/Tree_traversal/Tree_traversal.js create mode 100644 bona1122/[week5]Tree/Tree_traversal/input.txt diff --git a/bona1122/[week5]Tree/Tree_traversal/Tree_traversal.js b/bona1122/[week5]Tree/Tree_traversal/Tree_traversal.js new file mode 100644 index 0000000..90cd98d --- /dev/null +++ b/bona1122/[week5]Tree/Tree_traversal/Tree_traversal.js @@ -0,0 +1,40 @@ +// https://www.acmicpc.net/problem/2263 +const filePath = + process.platform === "linux" + ? "/dev/stdin" + : require("path").join(__dirname, "input.txt") +const input = require("fs").readFileSync(filePath).toString().trim().split("\n") +const log = console.log + +// n개의 정점존재, 이진트리의 inorder, postorder 주어지면, preorder 구하기 +const n = +input[0] +const inorder = input[1].split(" ").map(Number) +const postorder = input[2].split(" ").map(Number) +let result = "" + +// 매번 findIndex하니, 시간초과가 남. => inorder 값의 인덱스를 미리 Map에 저장해두기 +const inorderMap = new Map() +inorder.forEach((val, idx) => inorderMap.set(val, idx)) + +// postorder로 루트 알아내고, +// 그 정보를 통해 inorder에서 왼/오 서브트리 알아내기 +// iStart, iEnd: inorder 배열의 범위 +// pStart, pEnd: postorder 배열의 범위 +const preorder = (iStart, iEnd, pStart, pEnd) => { + if (iStart > iEnd || pStart > pEnd) return + + const root = postorder[pEnd] + const rootIdx = inorderMap.get(root) + result += `${root} ` + + const leftSize = rootIdx - iStart // 왼쪽 서브트리 크기 + + // 왼쪽 서브트리 처리 + preorder(iStart, rootIdx - 1, pStart, pStart + leftSize - 1) + + // 오른쪽 서브트리 처리 + preorder(rootIdx + 1, iEnd, pStart + leftSize, pEnd - 1) +} + +preorder(0, n - 1, 0, n - 1) +log(result.trim()) diff --git a/bona1122/[week5]Tree/Tree_traversal/input.txt b/bona1122/[week5]Tree/Tree_traversal/input.txt new file mode 100644 index 0000000..e3fe03c --- /dev/null +++ b/bona1122/[week5]Tree/Tree_traversal/input.txt @@ -0,0 +1,3 @@ +3 +1 2 3 +1 3 2 \ No newline at end of file