2022.08.16(Tues)
[TIL] Day77
[SEB FE] Day76
๊ทธ๋ํ์ ์ฌ๋ฌ ๊ตฌ์กฐ ์ค ๋จ๋ฑกํฅ ๊ทธ๋ํ ๊ตฌ์กฐ
๐ย Cycle์ด ์๋ ํ๋์ ์ฐ๊ฒฐ ๊ทธ๋ํ (Connected Graph)
โย Cycle
: ํ ์ ์ ์์ ์ถ๋ฐํ์ฌ ๋ค์ ์ถ๋ฐํ๋ ์ ์ ์ผ๋ก ๋์๊ฐ ๋, ๋ค๋ฅธ ์ ์ ๊ณผ ๊ฐ์ ์ ๊ฑฐ์ณ์ ๋์๊ฐ๋ ๊ฒ
โย ์๊ธฐ ๋ฃจํ
(self loof
): ๋ค๋ฅธ ์ ์ ์ ๊ฑฐ์น์ง ์๊ณ ์ ์ ์์ ์ง์ถํ๋ ๊ฐ์ ์ด ๋ค์ ์์ ์๊ฒ ์ง์
ํ๋ ๊ฒฝ์ฐ
Root
๋ผ๋ ํ๋์ ๊ผญ์ง์ ๋ฐ์ดํฐ๋ฅผ ์์์ผ๋ก ์ฌ๋ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ (edge
)์ผ๋ก ์ฐ๊ฒฐNode
๊ฐ ์ํ ๊ณ์ธต์ผ๋ก ์ฐ๊ฒฐ๋๋ฉด ๋ถ๋ชจ/์์ ๊ด๊ณLeaf Node
: ์์์ด ์๋ ๋
ธ๋ ๊น์ด(depth)
: ๋ฃจํธ๋ก๋ถํฐ ํ์ ๊ณ์ธต์ ํน์ ๋
ธ๋๊น์ง์ ๊น์ด(depth) ํํ โฌ๏ธ๋ ๋ฒจ(Level)
: ํธ๋ฆฌ ๊ตฌ์กฐ์์ ๊ฐ์ ๊น์ด๋ฅผ ๊ฐ์ง๊ณ ์๋ ๋
ธ๋๋คํ์ ๋
ธ๋(Sibling Node)
: ๊ฐ์ ๋ ๋ฒจ์ ๋๋ํ ์๋ ๋
ธ๋๋์ด(Height)
: ๋ฆฌํ ๋
ธ๋๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฃจํธ๊น์ง์ ๋์ด(Height) ํํ โฌ๏ธSub tree
: root์์ ๋ป์ด ๋์ค๋ ํฐ ํธ๋ฆฌ ๋ด๋ถ์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ถ ์์ ํธ๋ฆฌ Node
: ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ด๋ฃจ๋ ๋ชจ๋ ๊ฐ๋ณ ๋ฐ์ดํฐRoot
: ํธ๋ฆฌ ๊ตฌ์กฐ ์์์ ์ด ๋๋ ๋
ธ๋Parent node
: ๋ ๋
ธ๋๊ฐ ์ํ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์์ ๋ ์๋์ ์ผ๋ก ๋ฃจํธ์์ ๊ฐ๊น์ด ๋
ธ๋Child node
: ๋ ๋
ธ๋๊ฐ ์ํ๊ด๊ณ๋ก ์ฐ๊ฒฐ๋์ด ์์ ๋ ์๋์ ์ผ๋ก ๋ฃจํธ์์ ๋จผ ๋
ธ๋Leaf
: ํธ๋ฆฌ ๊ตฌ์กฐ์ ๋ ์ง์ ์ด๊ณ , ์์ ๋
ธ๋๊ฐ ์๋ ๋
ธ๋// Class๋ก Tree ๊ตฌํ ์์
class Tree {
// constructor๋ก ๋ง๋ ๊ฐ์ฒด = ํธ๋ฆฌ node!
constructor(value) {
this.value = value;
this.children = []; // ๋
ธ๋์ ์์ ๋
ธ๋๋ค์ ๋ด์ ์ ์๋๋ก
}
// [ํธ๋ฆฌ ์ฝ์
๋ฉ์๋ ์์ฑ]
insertNode(value) {
const childNode = new Tree(value); // tree์ ์์ ๋
ธ๋ ์์ฑ
this.children.push(childNode);
}
// [tree์์ value๊ฐ ํ์]
// ํธ๋ฆฌ ์์ ํด๋น ๊ฐ์ด ํฌํจ๋์ด ์๋์ง ํ์ธํ๋ ๋ฉ์๋
contains(value) {
// ํ์ฌ ๋
ธ๋์ value ๊ฐ๊ณผ ์ฐพ๋ ๊ฐ์ด ์ผ์นํ๋ค๋ฉด (๊ฐ์ด ํฌํจ๋์ด ์๋ค๋ฉด)
if (this.value === value) {
return true;
}
// ๊ฐ์ ์ฐพ์ ๋๊น์ง ์์ ๋
ธ๋ ์ํ => ๋
ธ๋์ children ๋ฐฐ์ด ํ์
for (let i = 0; i < this.children.length; i += 1) {
const childNode = this.children[i];
if (childNode.contains(value)) {
return true;
}
}
// ์ ๋ถ ํ์ํ์์๋ ๊ฐ์ ์ฐพ์ง ๋ชปํ๋ฉด false ๋ฐํ
return false;
}
}
// ---------------------------------------------------
// Tree ์ฌ์ฉ ์์
const rootNode = new Tree(null);
for (let i = 0; i <= 4; i++) {
if (rootNode.children[i]) {
rootNode.children[i].insertNode(i);
}
rootNode.insertNode(i);
}
rootNode; // {value: null, children: Array(5)}
rootNode.contains(5); // false
rootNode.contains(1); // true
โฐย
์ด์ง ํธ๋ฆฌ
(Binary tree
): ์์ ๋ ธ๋๊ฐ ์ต๋ 2๊ฐ์ธ ๋ ธ๋๋ค๋ก ๊ตฌ์ฑ๋ ํธ๋ฆฌ
โฐยBST
: ์ด์ง ํ์(binary search
) & ์ฐ๊ฒฐ ๋ฆฌ์คํธ(linked list
)๋ฅผ ๊ฒฐํฉํ ์ด์งํธ๋ฆฌ
์ ์ด์ง ํธ๋ฆฌ
(Full binary tree
): ๊ฐ ๋
ธ๋๊ฐ 0๊ฐ / 2๊ฐ ์์ ๋
ธ๋ ๊ฐ์ํฌํ ์ด์ง ํธ๋ฆฌ
(Perfect binary tree
): ์ ์ด์ง ํธ๋ฆฌ & ์์ ์ด์ง ํธ๋ฆฌ์ธ ๊ฒฝ์ฐ์์ ์ด์ง ํธ๋ฆฌ
(Complete binary tree
): ๋ง์ง๋ง ๋ ๋ฒจ์ ์ ์ธํ ๋ชจ๋ ๋
ธ๋๊ฐ ๊ฐ๋ ์ฐจ ์์ด์ผ ํ๊ณ , ๋ง์ง๋ง ๋ ๋ฒจ ๋
ธ๋๋ ์ ๋ถ ์ฐจ ์์ง ์์๋ ๋์ง๋ง ์ผ์ชฝ์ด ์ฑ์์ ธ์ผ ํจย ย ย ย โย ํธ๋ฆฌ ์์ ์ฐพ๊ณ ์ ํ๋ ๊ฐ์ด ์๋๋ผ๋ ์ต๋ h๋ฒ ์ฐ์ฐ/ํ์ ์งํ
// Class๋ก ์ด์งํ์ํธ๋ฆฌ(BST) ๊ตฌํ ์์
class BinarySearchTree {
// constructor๋ก ๋ง๋ ๊ฐ์ฒด๋ ์ด์ง ํ์ ํธ๋ฆฌ์ Node๊ฐ ๋จ
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
// [์ด์ง ํ์ ํธ๋ฆฌ ์ฝ์
๋ฉ์๋]
// tree์ value ์ถ๊ฐ
insert(value) {
// ์
๋ ฅ๊ฐ์ด ํ์ฌ ๋
ธ๋ ๊ฐ๋ณด๋ค ์๋ค๋ฉด, ์ผ์ชฝ ๋
ธ๋์์ ์งํ
if (value < this.value) {
// ์ผ์ชฝ์ด ๋น์ด์๋์ง ํ์ธ ํ ๊ฐ ์ฝ์
(์ฆ, this.left์ ์๋ฌด๊ฒ๋ ์์ ๊ฒฝ์ฐ, ์๋ก์ด ์์ ๋
ธ๋ ์ถ๊ฐ)
if (this.left === null) {
this.left = new BinarySearchTree(value);
}
// this.left์ ์์ ๋
ธ๋๊ฐ ์์ ๊ฒฝ์ฐ, ์์ ๋
ธ๋์์ insert ์ฌ๊ท ์ฌ์ฉ
else {
this.left.insert(value);
}
}
// ์
๋ ฅ๊ฐ์ด ํ์ฌ ๋
ธ๋๋ณด๋ค ํฌ๋ค๋ฉด, ์ค๋ฅธ์ชฝ ๋
ธ๋์์ ์งํ
else if (value > this.value) {
// this.right์ ์๋ฌด๊ฒ๋ ์์ ๊ฒฝ์ฐ, ์๋ก์ด ์์ ๋
ธ๋ ์ถ๊ฐ
if (this.right === null) {
this.right = new BinarySearchTree(value);
}
// this.left์ ์์ ๋
ธ๋๊ฐ ์์ ๊ฒฝ์ฐ, ์์ ๋
ธ๋์์ insert ์ฌ๊ท ์ฌ์ฉ
else {
this.right.insert(value);
}
} else {
// ์ด๋ฏธ value๊ฐ์ ํฌํจํ๊ณ ์์ผ๋ฏ๋ก ์๋ฌด๊ฒ๋ ํ์ง ์์
}
}
// [์ด์ง ํ์ ํธ๋ฆฌ ์์ ํด๋น ๊ฐ์ด ํฌํจ๋์ด ์๋์ง ํ์ธ ๋ฉ์๋]
// tree์ value๊ฐ ํ์
contains(value) {
// ์ฐพ๋ value๊ฐ์ด ๋
ธ๋์ value์ ์ผ์นํ๋ค๋ฉด, true ๋ฆฌํด
if (value === this.value) {
return true;
}
// ์ฐพ๋ value ๊ฐ์ด ํ์ฌ ๋
ธ๋์ value๋ณด๋ค ์๋ค๋ฉด, ์ผ์ชฝ์์ contains ์ฌ๊ท ์งํ
if (value < this.value) {
return !!(this.left && this.left.contains(value));
}
// ์ฐพ๋ value ๊ฐ์ด ํ์ฌ ๋
ธ๋์ value๋ณด๋ค ํฌ๋ค๋ฉด, ์ค๋ฅธ์ชฝ์์ contains ์ฌ๊ท ์งํ
if (value > this.value) {
return !!(this.right && this.right.contains(value));
}
}
// --------------------------------------------
// [Tree ์ ์ ์ํ]
preorder(callback) {
callback(this.value);
if (this.left) {
this.left.preorder(callback);
}
if (this.right) {
this.right.preorder(callback);
}
}
// [Tree ์ค์ ์ํ]
inorder(callback) {
if (this.left) {
this.left.inorder(callback);
}
callback(this.value);
if (this.right) {
this.right.inorder(callback);
}
}
// [Tree ํ์ ์ํ]
postorder(callback) {
if (this.left) {
this.left.postorder(callback);
}
if (this.right) {
this.right.postorder(callback);
}
callback(this.value);
}
}
โย ํธ๋ฆฌ ๊ตฌ์กฐ์์ ๋ ธ๋๋ฅผ ์์ฐจ์ ์ผ๋ก ์กฐํํ ๋์ ์์๋ ํญ์ ์ผ์ชฝ โ ์ค๋ฅธ์ชฝ
์ฌ๋ฌ๊ฐ์ ์ ๋ค์ด ์๋ก ๋ณต์กํ๊ฒ ์ฐ๊ฒฐ๋์ด ์๋ ๊ด๊ณ๋ฅผ ํํํ ์๋ฃ๊ตฌ์กฐ
์ ์
(vertex
): ํ๋์ ์ ๊ฐ์
(edge
): ํ๋์ ์ : ๊ฐ ์ ์ ์ด ์ด๋ค ์ ์ ๊ณผ ์ธ์ ํ๋์ง ๋ฆฌ์คํธ ํํ๋ก ํํ
: ์๋ก ๋ค๋ฅธ ์ ์ ๋ค์ด ์ธ์ ํ ์ํ์ธ์ง๋ฅผ ํ์ํ ํ๋ ฌ๋ก, 2์ฐจ์ ๋ฐฐ์ด ํํ๋ก ๋ํ๋
// Class๋ก ์ธ์ ํ๋ ฌ ๊ตฌํ ์์
// Directed graph(๋ฐฉํฅ ๊ทธ๋ํ)
// unweighted(๋น๊ฐ์ค์น)
// adjacency matrix(์ธ์ ํ๋ ฌ)
// ๊ธฐ์กด ๋ฐฐ์ด์ ์ธ๋ฑ์ค๋ฅผ ์ ์ ์ผ๋ก ์ฌ์ฉ(ex. 0, 1, 2, ... --> ์ ์ )
class GraphWithAdjacencyMatrix {
// constructor ๊ตฌํ
constructor() {
this.matrix = [];
}
// [vertex(์ ์ ) ์ถ๊ฐ]
addVertex() {
const currentLength = this.matrix.length;
for (let i = 0; i < currentLength; i++) {
this.matrix[i].push(0);
}
this.matrix.push(new Array(currentLength + 1).fill(0));
}
// [vertex(์ ์ ) ํ์]
contains(vertex) {
// this.matrix์ vertex ์กด์ฌ -> true, ์๋๋ฉด -> false ๋ฆฌํด
return !!this.matrix[vertex];
}
// [1. vertex(์ ์ )๊ณผ edge(๊ฐ์ ) ์ถ๊ฐ]
addEdge(from, to) {
const currentLength = this.matrix.length - 1;
if (from === undefined || to === undefined) {
console.log("2๊ฐ์ ์ธ์๊ฐ ์์ด์ผ ํฉ๋๋ค.");
return;
}
// ๊ฐ์ ์ ์ถ๊ฐํ ์ ์๋ ์ํฉ์์ ์ถ๊ฐ X
// from vertex์ to vertex๊ฐ ์ ์ฒด ๊ทธ๋ํ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ค๋ฉด return
if (from > currentLength || to > currentLength || from < 0 || to < 0) {
console.log("๋ฒ์๊ฐ ๋งคํธ๋ฆญ์ค ๋ฐ์ ์์ต๋๋ค.");
return;
}
// this.matrix[from][to]์ ๊ฐ์ 1๋ก ๋ฐ๊ฟ์ค -> edge์ผ๋ก ์ฐ๊ฒฐ์ด ๋์ด ์์ ํ์
this.matrix[from][to] = 1;
}
// 2. from vertex์ to vertex ์ฌ์ด์ edge๋ฅผ ๊ฐ์ง๊ณ ์๋์ง ํ๋จ
hasEdge(from, to) {
return !!this.matrix[from][to];
}
// [3. edge(๊ฐ์ ) ์ ๊ฑฐ]
// from vertex์ to vertex ์ฌ์ด์ ๊ด๋ จ์ด ์๋ค๋ฉด, edge ์ ๊ฑฐ
removeEdge(from, to) {
const currentLength = this.matrix.length - 1;
if (from === undefined || to === undefined) {
console.log("2๊ฐ์ ์ธ์๊ฐ ์์ด์ผ ํฉ๋๋ค.");
return;
}
// from vertex์ to vertex๊ฐ ์ ์ฒด ๊ทธ๋ํ์ ๋ฒ์๋ฅผ ๋ฒ์ด๋๋ค๋ฉด return
if (from > currentLength || to > currentLength || from < 0 || to < 0) {
console.log("๋ฒ์๊ฐ ๋งคํธ๋ฆญ์ค ๋ฐ์ ์์ต๋๋ค.");
return;
}
// ๊ฐ์ ์ญ์
// this.matrix[from][to]์ ๊ฐ์ 0์ผ๋ก ๋ฐ๊ฟ์ค -> ๊ด๋ จ ์์์ ํ์
this.matrix[from][to] = 0;
}
}
์ฐ๊ฒฐ ๊ทธ๋ํ
: ์ ์ ๋ค์ด ๊ฐ์ ์ผ๋ก ์ ๋ถ ์ฐ๊ฒฐ๋์ด ์๋ ๊ทธ๋ํ๋น์ฐ๊ฒฐ ๊ทธ๋ํ
: ์ ์ ์ด ํ๋๋ผ๋ ์ฐ๊ฒฐ๋์ด ์์ง ์์ ๊ทธ๋ํ๋น๊ฐ์ค์น ๊ทธ๋ํ
: ์ถ๊ฐ์ ์ธ ์ ๋ณด๋ฅผ ํ์
ํ ์ ์๋ ๊ทธ๋ํ๊ฐ์ค์น ๊ทธ๋ํ
: ๊ฐ์ ์ ์ฐ๊ฒฐ ๊ฐ๋๋ฅผ ํํํ ๊ทธ๋ํ: ๋๋น ์ฐ์ ํ์์ผ๋ก, ์ฃผ๋ก ๋ ์ ์ ์ฌ์ด ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ์ ๋ ์ฌ์ฉ
โย ์ถ๋ฐํ๋ ์ ์ ๊ณผ ๊ฐ์ฅ ๊ฐ๊น์ด ์ ์ ๋ถํฐ ํ์ํ๋ฏ๋ก ๊ฒฝ๋ก ํ์์ ๊ฐ์ฅ ๋จผ์ ์ฐพ์์ง๋ ํด๋ต์ด ๊ณง ์ต๋จ๊ฑฐ๋ฆฌ!
: ๊น์ด๋ฅผ ์ฐ์ ์ ์ผ๋ก ํ์ํ๋ ๋ฐฉ๋ฒ์ผ๋ก, ํ ์ ์ ์์ ๋ค์ ๊ฒฝ๋ก๋ก ๋์ด๊ฐ๊ธฐ ์ ์ ํด๋น ๊ฒฝ๋ก๋ฅผ ์๋ฒฝํ ํ์ํ ๋ ์ฌ์ฉ
โย BFS๋ณด๋จ ํ์ ์๊ฐ์ด ๋ ๊ฑธ๋ฆด์ง๋ผ๋ ๋ชจ๋ ๋
ธ๋๋ฅผ ์์ ํ ํ์ ๊ฐ๋ฅ