Skip to content
Merged
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
91 changes: 65 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,84 @@
## 미션 목표
- 자바스크립트로 정렬 알고리즘 구현하기
- 자바스크립트로 자료 구조 구현하기
- 자바스크립트로 힙 정렬 구현하기

## 요구사항
다음 정렬 알고리즘을 각각 JavaScript 함수로 구현해 주세요.
다음 자료 구조를 구현해 `algorithm` 폴더에 저장해 주세요.

### 선택 정렬 (Selection sort)
- [x] 숫자형 배열을 파라미터로 받고, 해당 배열을 수정하도록 구현합니다.
### 링크드 리스트 (Linked List)
- 파일 이름: `LinkedList.js`
- 클래스 이름: `LinkedList`
- 메서드:
- [x] `addNode(value)`: 리스트의 끝에 새 노드를 추가
- [x] `findNode(value)`: 주어진 값을 가지는 노드를 찾아 리턴
- [x] `insertAfter(targetValue, newValue)`: 특정 값을 가진 노드 뒤에 새 노드 추가
- [x] `removeAfter(targetValue)`: 특정 값을 가진 노드 뒤의 노드를 삭제

### 삽입 정렬 (Insertion sort)
- [x] 숫자형 배열을 파라미터로 받고, 해당 배열을 수정하도록 구현합니다.
### 이중 링크드 리스트 (Doubly Linked List)
- 파일 이름: `DoublyLinkedList.js`
- 클래스 이름: `DoublyLinkedList`
- 메서드:
- [x] `addToHead(value)`: 리스트의 앞쪽에 노드 추가
- [x] `addToTail(value)`: 리스트의 뒤쪽에 노드 추가
- [x] `insertAfter(targetValue, newValue)`: 특정 값을 가진 노드 뒤에 새 노드 추가
- [x] `findNode(value)`: 값을 가진 노드를 찾아 반환합니다.
- [x] `removeNode(value)`: 특정 값을 가진 노드 삭제

### 병합 정렬 (Merge sort)
- [x] 숫자형 배열을 파라미터로 받고, 정렬된 새로운 배열을 리턴하도록 구현합니다.
### 큐 (Queue)
- 파일 이름: `Queue.js`
- 클래스 이름: `Queue`
- 메서드:
- [x] `enqueue(value)`: 큐의 맨 뒤에 값을 추가
- [x] `dequeue()`: 큐의 앞에서 값을 제거하고 그 값을 리턴
- [x] `peek()`: 큐의 앞에 있는 값을 제거하지 않고 리턴
- [x] `isEmpty()`: 큐가 비어 있는지 불린형으로 리턴

### 퀵 정렬 (Quick sort)
- [x] 숫자형 배열을 파라미터로 받고, 해당 배열을 수정하도록 구현합니다.
### 스택 (Stack)
- 파일 이름: `Stack.js`
- 클래스 이름: `Stack`
- 메서드:
- [x] `push(value)`: 스택의 맨 위에 값을 추가
- [x] `pop()`: 스택의 맨 위 값을 제거하고 그 값을 리턴
- [x] `peek()`: 스택의 맨 위 값을 제거하지 않고 그 값을 리턴
- [x] `isEmpty()`: 스택이 비어 있는지 불린형으로 리턴

### 함수 예시:
해당 배열을 직접 수정하는 예시
```js
const nums = [3, 1, 2];
console.log(nums); // [3, 1, 2];
selectionSort(nums);
console.log(nums); // [1, 2, 3]
```
### 이진 탐색 트리 (Binary Search Tree)
- 파일 이름: `BinarySearchTree.js`
- 클래스 이름: `BinarySearchTree`
- 메서드:
- [x] `insert(value)`: 트리에 값 추가
- [x] `find(value)`: 주어진 값을 찾고 해당 노드를 리턴
- [x] `remove(value)`: 트리에서 해당 값을 삭제

다음 알고리즘을 JavaScript로 구현해 `algorithm/sorts.js` 파일에 추가로 작성해 주세요.

### 힙 정렬
- [x] 함수 이름: `heapsort()`
- 숫자형 배열을 받아서 받은 배열을 정렬된 상태로 수정

### 제출 안내
`algorithm` 폴더를 만들고 `sorts.js` 파일에 구현한 함수들을 작성해 주세요.
`algorithm` 폴더를 만들고 그 아래에 만든 파일들을 저장해 주세요.

---

## 멘토에게
- 기본 요구사항은 모두 충족하였으며, 추가 구현한 내용을 아래에 기재합니다.

### Tree Sort
- Binary Search Tree 기반의 정렬 알고리즘을 구현했습니다.
- 새로운 배열을 반환하며, 중위 순회를 이용해 오름차순 결과를 얻습니다
### Hash Table
- 문자열 해시 함수
- Chaining 방식 충돌 처리
- `put / get / remove / has` 포함

### Graph
- 인접 리스트 기반
- 단방향 / 양방향 간선 추가, 정점 조회 기능 포함

### BFS / DFS
- 인접 리스트를 대상으로 하는 기본 탐색 알고리즘

### CI
- `vitest` 기반 테스트 & `GitHub Actions CI`를 추가했습니다.
- `Vitest` 테스트 코드를 작성했습니다.
- 테스트 케이스는 아래와 같습니다.
- 기본 정렬 테스트
- 큰 배열(200개) 정렬 테스트
- 중복 요소 포함된 배열 테스트
- `sort.test.ts`(3): HeapSort 추가
- `datastructures.test`(12): LinkedList, DoublyLinkedList, Queue, Stack, BinarySearchTree
- `extra-datastructures.test.js`(10): HashTable, Graph, BFS, DFS
152 changes: 152 additions & 0 deletions algorithm/BinarySearchTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/**
* @file BinarySearchTree.js
* @description BST(이진 탐색 트리) 구현 클래스
*
* @details
* - 왼쪽 서브트리는 항상 작은 값
* - 오른쪽 서브트리는 항상 큰 값
* - 탐색, 삽입, 삭제가 평균 O(log n) 시간에 수행됨
*/

/**
* BST 노드 구조
*/
class TreeNode {
/**
* @param {number} value - 노드에 저장할 값
*/
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}

/**
* BST 트리
*/
export class BinarySearchTree {
constructor() {
/**
* @type {TreeNode | null}
*/
this.root = null;
}
/**
* 값을 트리에 삽입합니다.
*
* @param {number} value - 삽입할 값
* @returns {void}
*/
insert(value) {
this.root = this.#insertNode(this.root, value);
}

/**
* 내부 재귀용 삽입 함수
*
* @private
* @param {TreeNode | null} node
* @param {number} value
* @returns {TreeNode}
*/
#insertNode(node, value) {
if (node === null) return new TreeNode(value);

if (value < node.value) {
node.left = this.#insertNode(node.left, value);
} else {
node.right = this.#insertNode(node.right, value);
}

return node;
}

/**
* 값을 가진 노드를 탐색해 반환합니다.
*
* @param {number} value - 찾을 값
* @returns {TreeNode | null} 찾은 노드, 없으면 null
*/
find(value) {
return this.#findNode(this.root, value);
}

/**
* 내부 재귀용 탐색 함수
*
* @private
* @param {TreeNode | null} node
* @param {number} value
* @returns {TreeNode | null}
*/
#findNode(node, value) {
if (node === null) return null;

if (value === node.value) return node;
if (value < node.value) return this.#findNode(node.left, value);

return this.#findNode(node.right, value);
}

/**
* 값을 가진 노드를 트리에서 삭제합니다.
*
* @param {number} value - 삭제할 값
* @returns {void}
*/
remove(value) {
this.root = this.#removeNode(this.root, value);
}

/**
* 내부 재귀용 삭제 함수
*
* @private
* @param {TreeNode | null} node
* @param {number} value
* @returns {TreeNode | null}
*/
#removeNode(node, value) {
if (node === null) return null;

// 삭제 대상 값 탐색
if (value < node.value) {
node.left = this.#removeNode(node.left, value);
return node;
} else if (value > node.value) {
node.right = this.#removeNode(node.right, value);
return node;
}

// 일치 노드 발견 → 삭제 처리 시작
// 1. 자식 없음 (리프 노드)
if (!node.left && !node.right) return null;

// 2. 자식이 하나 (좌 or 우)
if (!node.left) return node.right;
if (!node.right) return node.left;

// 3. 자식이 둘 다 있음
// - 오른쪽 서브트리 min 값을 찾아 교체
const successor = this.#findMin(node.right);
node.value = successor.value;
node.right = this.#removeNode(node.right, successor.value);

return node;
}

/**
* 오른쪽 서브트리에서 min 노드룰 찾는 함수
*
* @private
* @param {TreeNode} node
* @returns {TreeNode}
*/
#findMin(node) {
while (node.left) {
node = node.left;
}
return node;
}
}
Loading