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주차 과제 구현 #2

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 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
91 changes: 91 additions & 0 deletions problem-1/SymbolTableWithArray.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,95 @@
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;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

  get(key) {
    return this.#items.find((item) => item.key === key)?.item;
  }

이렇게 더 많이 쓰긴 합니다. 왜냐하면 node라는 변수 혹은 상수를 사용하는 순간

  get(key) {
    const node = this.#items.find((item) => item.key === key);

    // 여기에 다른 누군가가 node를 가지고 무언가를 할 수 있는 가능성이 생김.

    return node?.item;
  }

그래서 아예 그런 의도를 차단할려면 변수를 생성하지 않는게 좋을 수도 있습니다

Copy link
Author

Choose a reason for hiding this comment

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

요즘 습관적으로 변수 선언해서 값을 받은 다음 리턴하는 구조로 코드를 작성하고 있는데, 말씀해주신 대로 변수를 선언할 경우 다른 사람이 선언한 변수를 이용할 가능성도 있겠네요! 감사합니다


put(key, item) {
const curIndex = this.#findIndex(key);

if (curIndex >= 0) {
this.#items[curIndex].item = item;

return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

    const curIndex = this.#findIndex(key);
    if (curIndex >= 0) {
      this.#items[curIndex].item = item;

      return;
    }

개인적인 의견이지만, 이 사이는 붙이는게 좋은 것 같아요. 바로 위 코드랑 연관이 높고, 나온 값에 대해서 처리를 하는거라서 붙이는게 좋은 것 같아요. 아마 제가 Golang을 사용해서 영향을 받은 것도 있는 것 같기도 하고요. Golang에서는 이런 문법은 많이 쓰거든요.

data, err := getSomething
if err == nil {
    return
}

Copy link
Author

Choose a reason for hiding this comment

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

이것도 제 습관이네요 ㅠ
변수 선언하고 항상 한 줄 씩 띄우고 있었는데, 코드가 연관될 경우 라인을 붙이는 것도 좋은 것 같습니다! 감사합니다


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);
}

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 = {
Expand Down
16 changes: 16 additions & 0 deletions problem-1/problem-1.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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']);
});
69 changes: 59 additions & 10 deletions problem-2/SymbolTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);

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

// 대소 비교로 범위 지정
if (this.#keys[mid] > key) {
end = mid - 1;
} else {
start = mid + 1;
}
}

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);
}
return mid;
return start;
}

min() {
Expand Down Expand Up @@ -106,15 +116,54 @@ class SymbolTable {
}

contains(key) {
const i = this.rank(key);

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

return false;
}

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) {
const i = this.rank(key);

if (i >= this.#n) {
return;
}

return this.#keys[i];
}

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;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

주어진 시작 키보다 큰 수 중에 가장 작은 수의 위치, 주어진 끝 키보다 작은 수 중에 가장 큰 키의 위치를 구해서, 해당 구간의 모든 키 목록을 반환하는거군요 ㅎㅎ 기존 메서드를 활용해서 구현해 주셨네요

Copy link
Author

Choose a reason for hiding this comment

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

네 ㅎㅎ ceiling이랑 floor 메서드를 이용하면 되겠네! 라는 생각이 순간적으로 들어서 구현했는데, 잘 되더라구요!

변수명이 i, j로 작성되어 있어서 가독성이 떨어지네요 ..!

}

Expand Down
59 changes: 54 additions & 5 deletions 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) {
h;

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

Expand All @@ -23,10 +26,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;
Expand Down Expand Up @@ -58,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) {
Expand All @@ -69,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;
}

Expand Down Expand Up @@ -160,9 +166,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);
}

Expand Down Expand Up @@ -212,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;
}

Expand Down Expand Up @@ -269,6 +279,45 @@ class SymbolTable {

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

height() {
if (this.isEmpty()) {
return -1;
}

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

// 재귀적인 방법으로 트리의 높이 구하기 1
// #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));
// }

// 재귀적인 방법으로 트리의 높이 구하기 2
// #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));
// }

// eslint-disable-next-line class-methods-use-this
#height(node) {
if (node === undefined) {
return -1;
}

return node.h;
}
}

module.exports = {
Expand Down
Loading