Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4주차 과제 #4

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions problem-1/SymbolTableWithArray.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,76 @@
class SymbolTable {
#keys = [];

#values = [];

#n = 0;

constructor(max = 10) {
this.#keys = new Array(max);
this.#values = new Array(max);
}

get(key) {
for (let i = 0; i < this.#n; i++) {
if (this.#keys[i] === key) {
return this.#values[i];
}
}
}

put(key, value) {
for (let i = 0; i < this.#n; i++) {
if (this.#keys[i] === key) {
this.#values[i] = value;
return;
}
}

this.#keys[this.#n] = key;
this.#values[this.#n] = value;
this.#n++;
}

delete(key) {
for (let i = 0; i < this.#n; i++) {
if (this.#keys[i] === key) {
this.#values[i] = null;

for (let j = i; j < this.#n - 1; j++) {
this.#keys[j] = this.#keys[j + 1];
this.#values[j] = this.#values[j + 1];
}

this.#n--;
return;
}
}
}

contains(key) {
if (this.get(key)) {
return true;
}
return false;
Comment on lines +51 to +54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JavaScript에서 이런 경우 이렇게도 많이 씁니다.

return !!this.get(key);

변수 앞에 !를 붙이면 true -> false, false -> true로 바뀌잖아요. 이걸 2번 하면 true -> false -> true가 되겠죠. 어차피 아무것도 안하는데 왜 쓰냐고 할 수 있지만, 자바스크립트에는 Truthy와 Falsy가 있어요. 1, {}, [], 길이 1이상 문자열 등등은 true라고 가정하고, undefined, null, 0, "" 빈 문자열 등은 false라고 가정하죠.

그래서 어떤 객체가 주어졌을 때 !를 하나 붙이면 false가 되고 여기서 !를 하나 더 붙이면 true가 되므로 어떤 값이 있다는 것을 boolean변수로 변환할 수 있죠.

See also

}

isEmpty() {
if (this.#n === 0) {
return true;
} return false;
Comment on lines +58 to +60
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return this.#n === 0;

이렇게 써도 되겠네요

}

size() {
return this.#n;
}

keys() {
return this.#keys;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

각 속성들을 private으로 선언한 이유가 외부에서 함 부로 접근하고 수정하지 못하도록 한거예요. 여기서 this.#keys를 직접 반환하게 되면 외부에서 값을 조작할 수 있어서 위험할 수 있어요. 이럴 때는 복사해서 넘겨주는게 좋습니다. 그러면 복사한 값을 고쳐도 안에 있는 값에는 영향을 받지 않아요.

return [...this.#keys];

}

values() {
return this.#values;
}
}

module.exports = {
Expand Down
29 changes: 29 additions & 0 deletions problem-2/SymbolTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,44 @@ class SymbolTable {
}

contains(key) {
if (this.get(key)) {
return true;
} return false;
}

floor(key) {
const i = this.rank(key);
if (i === 0) {
return this.#keys[i] === key ? key : undefined;
}

if (this.#keys[i] === key) {
return key;
}

return this.#keys[i - 1];
}

ceiling(key) {
const i = this.rank(key);
return this.#keys[i];
}

keysRange(start, end) {
const startIndex = this.rank(start);
const endIndex = this.rank(end);

const arr = [];

for (let i = startIndex; i < endIndex; i++) {
arr.push(this.#keys[i]);
}

if (this.#keys[endIndex] === end) {
arr.push(end);
}

return arr;
}
}

Expand Down
20 changes: 19 additions & 1 deletion problem-3/SymbolTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ class Node {

n;

constructor(key, value, n) {
height;

constructor(key, value, n, height = 0) {
this.key = key;
this.value = value;
this.n = n;
this.height = height;
}
}

Expand Down Expand Up @@ -70,6 +73,7 @@ class SymbolTable {
}

node.n = this.#size(node.left) + this.#size(node.right) + 1;
node.height = Math.max(this.#height(node.left), this.#height(node.right)) + 1;
return node;
}

Expand Down Expand Up @@ -181,6 +185,7 @@ class SymbolTable {

node.left = this.#deleteMin(node.left);
node.n = this.#size(node.left) + this.#size(node.right) + 1;
node.height = Math.max(this.#height(node.left), this.#height(node.right)) + 1;
return node;
}

Expand Down Expand Up @@ -210,6 +215,7 @@ class SymbolTable {
node = this.min(t.right);
node.right = this.#deleteMin(t.right);
node.left = t.left;
node.height = Math.max(this.#height(node.left), this.#height(node.right)) + 1;
}

node.n = this.#size(node.left) + this.#size(node.right) + 1;
Expand Down Expand Up @@ -269,6 +275,18 @@ class SymbolTable {

return this.#max(node.right);
}

height() {
return this.#height(this.#root);
}

#height(node) {
if (node === undefined) {
return -1;
}

return node.height;
}
}

module.exports = {
Expand Down
77 changes: 75 additions & 2 deletions problem-5/LinearProbingHashTable.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
class LinearProbingHashTable {
#N = 0;

#M = 0;

#keys = [];

#values = [];

constructor(maxCount = 16) {
Expand All @@ -19,25 +22,95 @@ class LinearProbingHashTable {
}

hash(key) {
return this.#hash(key)
return this.#hash(key);
}

get(key) {
for (let i = this.#hash(key); this.#keys[i] !== undefined; i = (i + 1) % this.#M) {
if (this.#keys[i] === key) {
return this.#values[i];
}
}
}

put(key, value) {
let i = this.#hash(key);
while (true) {
if (this.#keys[i] === key) {
this.#values[i] = value;
return;
}

if (this.#keys[i] === undefined) {
this.#N++;
this.#keys[i] = key;
this.#values[i] = value;

if (this.#N >= this.#M / 2) {
this.#resize(this.#M * 2);
}

return;
}

i = (i + 1) % this.#M;
}
}

delete(key) {
for (let i = this.#hash(key); this.#keys[i] !== undefined; i = (i + 1) % this.#M) {
if (this.#keys[i] === key) {
// 찾았다.
this.#keys[i] = undefined;
this.#values[i] = undefined;
this.#N--;

i = (i + 1) % this.#M;
while (this.#keys[i] !== undefined) {
const beforeKey = this.#keys[i];
const beforeValuse = this.#values[i];

this.#keys[i] = undefined;
this.#values[i] = undefined;
this.#N--;
if (this.#N <= this.#M / 2) {
this.#resize(this.#M / 2);
}
this.put(beforeKey, beforeValuse);
i = (i + 1) % this.#M;
}
return;
}
}
}

contains(key) {
return this.get(key) !== undefined;
}

keys() {
return this.#keys.filter((key) => key !== undefined);
}

// 크기를 2배로 키운다.
#resize(capacity) {
// 이전 배열의 크기의 2배인 새로운 배열 하나 만든다.
// 이전에 배열을 꺼내서 다시 새로운 배열에 넣는다.

const newTable = new LinearProbingHashTable(capacity);

for (let i = 0; i < this.#M; i++) {
const key = this.#keys[i];
const value = this.#values[i];

if (key !== undefined) {
newTable.put(key, value);
}
}

this.#keys = newTable.#keys;
this.#values = newTable.#values;
this.#M = capacity;
}
}

Expand All @@ -53,7 +126,7 @@ const randomString = (max) => {
}

return result;
}
};

test('이미 있는 키 값에 값을 추가하면 이전 값을 덮어쓴다', () => {
const st = new LinearProbingHashTable();
Expand Down
Loading