From 69caba8df8de736fa204efa8509c1191274e5f2a Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Mon, 2 Oct 2023 22:46:53 +0900 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20problem-1=20SymbolTableWithArray?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-1/SymbolTableWithArray.js | 64 +++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/problem-1/SymbolTableWithArray.js b/problem-1/SymbolTableWithArray.js index 761c9ef..0ea08e9 100644 --- a/problem-1/SymbolTableWithArray.js +++ b/problem-1/SymbolTableWithArray.js @@ -1,4 +1,68 @@ +class Node { + key; + + item; + + constructor(key, item) { + this.key = key; + this.item = item; + } +} + class SymbolTable { + #items = []; + + #n = 0; + + size() { + return this.#n; + } + + isEmpty() { + return this.size() === 0; + } + + #findIndex(key) { + return this.#items.findIndex((item) => item.key === key); + } + + get(key) { + const node = this.#items.find((item) => item.key === key); + + return node?.item; + } + + put(key, item) { + const curIndex = this.#findIndex(key); + + if (curIndex >= 0) { + this.#items[curIndex].item = item; + + return; + } + + const node = new Node(key, item); + + this.#items[this.#n] = node; + + this.#n += 1; + } + + delete(key) { + const index = this.#findIndex(key); + + if (index < 0) { + return; + } + + this.#items.splice(index, 1); + + this.#n -= 1; + } + + contains(key) { + return !!this.get(key); + } } module.exports = { From a59592e4f40f42721516849b0007dff0c3b96e8a Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Mon, 2 Oct 2023 22:55:37 +0900 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20problem-1=20SymbolTableWithArray?= =?UTF-8?q?=20keys=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-1/SymbolTableWithArray.js | 27 +++++++++++++++++++++++++++ problem-1/problem-1.test.js | 16 ++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/problem-1/SymbolTableWithArray.js b/problem-1/SymbolTableWithArray.js index 0ea08e9..f377b53 100644 --- a/problem-1/SymbolTableWithArray.js +++ b/problem-1/SymbolTableWithArray.js @@ -63,6 +63,33 @@ class SymbolTable { contains(key) { return !!this.get(key); } + + values() { + return this.#items.map(({ item }) => item); + } + + keys() { + const data = [...this.#items]; + let index = 0; + + return { + [Symbol.iterator]() { + return { + next() { + if (index >= data.length) { + return { done: true }; + } + + const { key } = data[index]; + + index += 1; + + return { done: false, value: key }; + }, + }; + }, + }; + } } module.exports = { diff --git a/problem-1/problem-1.test.js b/problem-1/problem-1.test.js index 9f38cf6..a8fedbe 100644 --- a/problem-1/problem-1.test.js +++ b/problem-1/problem-1.test.js @@ -124,3 +124,19 @@ test('심볼 테이블은 키에 해당하는 값을 저장한다', () => { expect(st.get('something')).toBeUndefined(); expect(st.get('this')).toBeUndefined(); }); + +test('키를 순회할 수 있다', () => { + const st = new SymbolTable(); + + st.put('foo', 'bar'); + st.put('something', 'that'); + st.put('this', 'is'); + + const keys = []; + + for (const key of st.keys()) { + keys.push(key); + } + + expect(keys).toEqual(['foo', 'something', 'this']); +}); From c3fa9140fc4f4d20cc580d73656187c5b283854e Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 16:43:10 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20problem-2=20contains=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/SymbolTable.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/problem-2/SymbolTable.js b/problem-2/SymbolTable.js index 6bb3c68..01934e7 100644 --- a/problem-2/SymbolTable.js +++ b/problem-2/SymbolTable.js @@ -106,6 +106,13 @@ class SymbolTable { } contains(key) { + const i = this.rank(key); + + if (key === this.#keys[i] && i < this.#n) { + return true; + } + + return false; } floor(key) { From 3d1f352bd3217923781a0c10dc9713058d98ca04 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 16:44:22 +0900 Subject: [PATCH 04/13] =?UTF-8?q?feat:=20problem-2=20floor=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/SymbolTable.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/problem-2/SymbolTable.js b/problem-2/SymbolTable.js index 01934e7..a431d5a 100644 --- a/problem-2/SymbolTable.js +++ b/problem-2/SymbolTable.js @@ -116,6 +116,17 @@ class SymbolTable { } floor(key) { + const i = this.rank(key); + + if (key === this.#keys[i]) { + return key; + } + + if (i === 0) { + return; + } + + return this.#keys[i - 1]; } ceiling(key) { From f6e3433deb7c0b9b6d7b83f1b1124709dc5648cd Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 16:47:07 +0900 Subject: [PATCH 05/13] =?UTF-8?q?feat:=20problem-2=20ceiling=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/SymbolTable.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/problem-2/SymbolTable.js b/problem-2/SymbolTable.js index a431d5a..31eadca 100644 --- a/problem-2/SymbolTable.js +++ b/problem-2/SymbolTable.js @@ -130,6 +130,13 @@ class SymbolTable { } ceiling(key) { + const i = this.rank(key); + + if (i >= this.#n) { + return; + } + + return this.#keys[i]; } keysRange(start, end) { From 499034548091dc7a23b92afa5e4b4275bcd85482 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 16:53:55 +0900 Subject: [PATCH 06/13] =?UTF-8?q?feat:=20problem-2=20keysRange=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/SymbolTable.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/problem-2/SymbolTable.js b/problem-2/SymbolTable.js index 31eadca..64405d6 100644 --- a/problem-2/SymbolTable.js +++ b/problem-2/SymbolTable.js @@ -140,6 +140,20 @@ class SymbolTable { } keysRange(start, end) { + const i = this.rank(this.ceiling(start)); + const j = this.rank(this.floor(end)); + + if (i > j || i < 0 || j >= this.#n) { + return []; + } + + const keys = []; + + for (let k = i; k <= j; k++) { + keys.push(this.#keys[k]); + } + + return keys; } } From a893efcdcbb6920d1bf33dbc512c947961628392 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 17:07:10 +0900 Subject: [PATCH 07/13] =?UTF-8?q?feat:=20problem-2=20rank=20=EB=B0=98?= =?UTF-8?q?=EB=B3=B5=EB=AC=B8=EC=9C=BC=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/SymbolTable.js | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/problem-2/SymbolTable.js b/problem-2/SymbolTable.js index 64405d6..71d5dbc 100644 --- a/problem-2/SymbolTable.js +++ b/problem-2/SymbolTable.js @@ -63,18 +63,28 @@ class SymbolTable { this.#n--; } - rank(key, start = 0, end = this.#n - 1) { - if (start > end) { - return start; - } + rank(key) { + let mid = 0; + let start = 0; + let end = this.#n - 1; + + while (start <= end) { + // 가운데 인덱스 + mid = Math.floor((start + end) / 2); - const mid = start + Math.floor((end - start) / 2); - if (key < this.#keys[mid]) { - return this.rank(key, start, mid - 1); - } if (key > this.#keys[mid]) { - return this.rank(key, mid + 1, end); + if (this.#keys[mid] === key) { + return mid; + } + + // 대소 비교로 범위 지정 + if (this.#keys[mid] > key) { + end = mid - 1; + } else { + start = mid + 1; + } } - return mid; + + return start; } min() { From b91dccc42535a8580e8e735ad257c4dad3679418 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 23:17:00 +0900 Subject: [PATCH 08/13] =?UTF-8?q?feat:=20problem-3=20height=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=9E=AC=EA=B7=80=EB=A1=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-3/SymbolTable.js | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/problem-3/SymbolTable.js b/problem-3/SymbolTable.js index 8bff19c..0275965 100644 --- a/problem-3/SymbolTable.js +++ b/problem-3/SymbolTable.js @@ -23,10 +23,12 @@ class SymbolTable { return this.#root === undefined; } + // 테이블의 사이즈 반환 = 모든 노드의 개수 size() { return this.#size(this.#root); } + // eslint-disable-next-line class-methods-use-this #size(node) { if (node === undefined) { return 0; @@ -160,9 +162,12 @@ class SymbolTable { if (key < node.key) { return this.#rank(node.left, key); - } if (key > node.key) { + } + + if (key > node.key) { return 1 + this.#size(node.left) + this.#rank(node.right, key); } + return this.#size(node.left); } @@ -269,6 +274,35 @@ class SymbolTable { return this.#max(node.right); } + + height() { + if (this.isEmpty()) { + return -1; + } + + // 재귀적인 방법으로 트리의 높이 구하기 + return this.#height(this.#root); + } + + // #height(node, h = 0) { + // if (node === undefined) { + // return h - 1; + // } + + // return Math.max(this.#height(node.left, 1 + h), this.#height(node.right, 1 + h)); + // } + + #height(node) { + if (!node) { + return 0; + } + + if (!node.left && !node.right) { + return 0; + } + + return 1 + Math.max(this.#height(node.left), this.#height(node.right)); + } } module.exports = { From 90b1555a787638df8495cc09311f8090b3bb15bd Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Tue, 3 Oct 2023 23:37:44 +0900 Subject: [PATCH 09/13] =?UTF-8?q?feat:=20problem-3=20height=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EB=B3=80=EC=88=98=EB=A5=BC=20=EC=9D=B4=EC=9A=A9?= =?UTF-8?q?=ED=95=B4=EC=84=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-3/SymbolTable.js | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/problem-3/SymbolTable.js b/problem-3/SymbolTable.js index 0275965..ee77f09 100644 --- a/problem-3/SymbolTable.js +++ b/problem-3/SymbolTable.js @@ -9,10 +9,13 @@ class Node { n; - constructor(key, value, n) { + h; + + constructor(key, value, n, h = 0) { this.key = key; this.value = value; this.n = n; + this.h = h; } } @@ -60,7 +63,7 @@ class SymbolTable { #put(node, key, value) { if (node === undefined) { - return new Node(key, value, 1); + return new Node(key, value, 1, 0); } if (key < node.key) { @@ -71,7 +74,8 @@ class SymbolTable { node.value = value; } - node.n = this.#size(node.left) + this.#size(node.right) + 1; + node.n = 1 + this.#size(node.left) + this.#size(node.right); + node.h = 1 + Math.max(this.#height(node.left), this.#height(node.right)); return node; } @@ -217,7 +221,8 @@ class SymbolTable { node.left = t.left; } - node.n = this.#size(node.left) + this.#size(node.right) + 1; + node.n = 1 + this.#size(node.left) + this.#size(node.right); + node.h = 1 + Math.max(this.#height(node.left), this.#height(node.right)); return node; } @@ -280,10 +285,10 @@ class SymbolTable { return -1; } - // 재귀적인 방법으로 트리의 높이 구하기 return this.#height(this.#root); } + // 재귀적인 방법으로 트리의 높이 구하기 1 // #height(node, h = 0) { // if (node === undefined) { // return h - 1; @@ -292,16 +297,26 @@ class SymbolTable { // return Math.max(this.#height(node.left, 1 + h), this.#height(node.right, 1 + h)); // } - #height(node) { - if (!node) { - return 0; - } + // 재귀적인 방법으로 트리의 높이 구하기 2 + // #height(node) { + // if (!node) { + // return 0; + // } - if (!node.left && !node.right) { - return 0; + // if (!node.left && !node.right) { + // return 0; + // } + + // return 1 + Math.max(this.#height(node.left), this.#height(node.right)); + // } + + // eslint-disable-next-line class-methods-use-this + #height(node) { + if (node === undefined) { + return -1; } - return 1 + Math.max(this.#height(node.left), this.#height(node.right)); + return node.h; } } From d7049dafd95ccb105f5a21d4b8fab103f68c978f Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Mon, 9 Oct 2023 22:46:09 +0900 Subject: [PATCH 10/13] =?UTF-8?q?feat:=20problem-5=20=EA=B0=9C=EB=B3=84=20?= =?UTF-8?q?=EC=B2=B4=EC=9D=B4=EB=8B=9D=20=ED=95=B4=EC=8B=9C=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-5/SeperateChainingHashTable.test.js | 39 ++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/problem-5/SeperateChainingHashTable.test.js b/problem-5/SeperateChainingHashTable.test.js index 6f9e2b1..11022ce 100644 --- a/problem-5/SeperateChainingHashTable.test.js +++ b/problem-5/SeperateChainingHashTable.test.js @@ -1,8 +1,18 @@ +const { SymbolTableWithLinkedList } = require('../problem-1/SymbolTableWithLinkedList'); + class SeperateChainingHashTable { #M; + #table; + constructor(maxCount = 997) { this.#M = maxCount; + + this.#table = new Array(maxCount); + + for (let i = 0; i < maxCount; i++) { + this.#table[i] = new SymbolTableWithLinkedList(); + } } #hash(key) { @@ -14,22 +24,43 @@ class SeperateChainingHashTable { } hash(key) { - return this.#hash(key) + return this.#hash(key); } get(key) { + const index = this.hash(key); + + return this.#table[index].get(key); } put(key, value) { + const index = this.hash(key); + + return this.#table[index].put(key, value); } - delete(key, value) { + delete(key) { + const index = this.hash(key); + + return this.#table[index].delete(key); } - + contains(key) { + return !!this.get(key); } keys() { + const result = []; + + this.#table.forEach((table) => { + const keys = table.keys(); + + for (const key of keys) { + result.push(key); + } + }); + + return result; } } @@ -45,7 +76,7 @@ const randomString = (max) => { } return result; -} +}; test('이미 있는 키 값에 값을 추가하면 이전 값을 덮어쓴다', () => { const st = new SeperateChainingHashTable(); From 259c4d81657b7df3d95a7e071f59ca5799495c54 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Wed, 11 Oct 2023 01:18:08 +0900 Subject: [PATCH 11/13] =?UTF-8?q?refactor:=20problem-1=20get=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EB=B3=80=EC=88=98=20=EC=84=A0=EC=96=B8=20?= =?UTF-8?q?=EC=97=86=EC=9D=B4=20=EB=B0=94=EB=A1=9C=20=EA=B0=92=20=EB=A6=AC?= =?UTF-8?q?=ED=84=B4=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-1/SymbolTableWithArray.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/problem-1/SymbolTableWithArray.js b/problem-1/SymbolTableWithArray.js index f377b53..f0712b2 100644 --- a/problem-1/SymbolTableWithArray.js +++ b/problem-1/SymbolTableWithArray.js @@ -27,9 +27,7 @@ class SymbolTable { } get(key) { - const node = this.#items.find((item) => item.key === key); - - return node?.item; + return this.#items.find((item) => item.key === key)?.item; } put(key, item) { From 9ef37cfd4527ff28eea00ad62920d63fef5e8665 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Wed, 11 Oct 2023 01:18:49 +0900 Subject: [PATCH 12/13] =?UTF-8?q?refactor:=20problem-1=20put=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=97=B0=EA=B4=80=EB=90=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EB=8A=94=20=EB=B6=99=EC=97=AC=EC=84=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-1/SymbolTableWithArray.js | 1 - 1 file changed, 1 deletion(-) diff --git a/problem-1/SymbolTableWithArray.js b/problem-1/SymbolTableWithArray.js index f0712b2..80fa60b 100644 --- a/problem-1/SymbolTableWithArray.js +++ b/problem-1/SymbolTableWithArray.js @@ -32,7 +32,6 @@ class SymbolTable { put(key, item) { const curIndex = this.#findIndex(key); - if (curIndex >= 0) { this.#items[curIndex].item = item; From 6dabc2f16f169a7f5ca1a3e99f8c5b80bed04ab9 Mon Sep 17 00:00:00 2001 From: seungwoo Kim Date: Wed, 11 Oct 2023 01:20:43 +0900 Subject: [PATCH 13/13] =?UTF-8?q?refactor:=20problem-2=20=EA=B0=80?= =?UTF-8?q?=EB=8F=85=EC=84=B1=EC=9D=84=20=EC=9C=84=ED=95=B4=20keysRange=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=20=EB=B3=80=EC=88=98=EB=AA=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- problem-2/SymbolTable.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/problem-2/SymbolTable.js b/problem-2/SymbolTable.js index 71d5dbc..c3eecab 100644 --- a/problem-2/SymbolTable.js +++ b/problem-2/SymbolTable.js @@ -150,16 +150,16 @@ class SymbolTable { } keysRange(start, end) { - const i = this.rank(this.ceiling(start)); - const j = this.rank(this.floor(end)); + const startIndex = this.rank(this.ceiling(start)); + const endIndex = this.rank(this.floor(end)); - if (i > j || i < 0 || j >= this.#n) { + if (startIndex > endIndex || startIndex < 0 || endIndex >= this.#n) { return []; } const keys = []; - for (let k = i; k <= j; k++) { + for (let k = startIndex; k <= endIndex; k++) { keys.push(this.#keys[k]); }