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
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Test

on:
push:
branches: ['**']
pull_request:

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Use Node 20
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install dependencies
run: npm install

- name: Run tests
run: npm test
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
## 미션 목표
- 자바스크립트로 정렬 알고리즘 구현하기

## 요구사항
다음 정렬 알고리즘을 각각 JavaScript 함수로 구현해 주세요.

### 선택 정렬 (Selection sort)
- [x] 숫자형 배열을 파라미터로 받고, 해당 배열을 수정하도록 구현합니다.

### 삽입 정렬 (Insertion sort)
- [x] 숫자형 배열을 파라미터로 받고, 해당 배열을 수정하도록 구현합니다.

### 병합 정렬 (Merge sort)
- [x] 숫자형 배열을 파라미터로 받고, 정렬된 새로운 배열을 리턴하도록 구현합니다.

### 퀵 정렬 (Quick sort)
- [x] 숫자형 배열을 파라미터로 받고, 해당 배열을 수정하도록 구현합니다.

### 함수 예시:
해당 배열을 직접 수정하는 예시
```js
const nums = [3, 1, 2];
console.log(nums); // [3, 1, 2];
selectionSort(nums);
console.log(nums); // [1, 2, 3]
```

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

---

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

### Tree Sort
- Binary Search Tree 기반의 정렬 알고리즘을 구현했습니다.
- 새로운 배열을 반환하며, 중위 순회를 이용해 오름차순 결과를 얻습니다

### CI
- `vitest` 기반 테스트 & `GitHub Actions CI`를 추가했습니다.
- 테스트 케이스는 아래와 같습니다.
- 기본 정렬 테스트
- 큰 배열(200개) 정렬 테스트
- 중복 요소 포함된 배열 테스트
197 changes: 197 additions & 0 deletions algorithm/sorts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
/**
* 선택 정렬(Selection Sort)
* @description 배열을 직접 수정하여 오름차순으로 정렬합니다.
*
* @param {number[]} arr - 정렬할 배열
* @returns {number[]} 정렬된 배열(원본 수정)
*/
export const selectionSort = (arr) => {
const n = arr.length;

for (let i = 0; i < n - 1; i++) {
let minIdx = i;
for (let j = i + 1; j < n; j++) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
// swap
[arr[i], arr[minIdx]] = [arr[minIdx], arr[i]];
}
return arr;
};

/**
* 삽입 정렬 (Insertion Sort)
* @description 배열을 직접 수정하여 오름차순으로 정렬합니다.
*
* @param {number[]} arr - 정렬할 배열
* @@returns {number[]} 정렬된 배열(원본 수정)
*/
export const insertionSort = (arr) => {
const n = arr.length;
for (let i = 1; i < n; i++) {
const key = arr[i];
let j = i - 1;

// key 위치 탐색
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
j--;
}

arr[j + 1] = key;
}
return arr;
};

/**
* Merge Sort의 파티션 함수
* @description 두 정렬된 배열을 병합하여 새로운 정렬 배열을 생성합니다.
*
* @param {number[]} left - 정렬된 왼쪽 배열
* @param {number[]} right - 정렬된 오른쪽 배열
* @returns {number[]} 병합된 새 배열
*/
const merge = (left, right) => {
const result = [];
let [i, j] = [0, 0];

while (i < left.length && j < right.length) {
if (left[i] <= right[j]) {
result.push(left[i]);
i++;
} else {
result.push(right[j]);
j++;
}
}

return [...result, ...left.slice(i), ...right.slice(j)];
};

/**
* 병합 정렬 (Merge Sort)
* 새로운 배열을 반환하며 원본 배열은 변경하지 않습니다.
*
* @param {number[]} arr - 정렬할 배열
* @returns {number[]} 정렬된 새로운 배열
*/
export const mergeSort = (arr) => {
if (arr.length <= 1) return arr;

const mid = Math.floor(arr.length / 2);
const left = mergeSort(arr.slice(0, mid));
const right = mergeSort(arr.slice(mid));

return merge(left, right);
};

/**
* QuickSort의 파티션 함수
* @description pivot을 기준으로 배열을 분할하고 pivot의 최종 위치를 반환합니다.
*
* @param {number[]} arr
* @param {number} left
* @param {number} right
* @returns {number} pivot의 최종 인덱스
*/
const partition = (arr, left, right) => {
const pivot = arr[right];
let i = left;

for (let j = left; j < right; j++) {
if (arr[j] < pivot) {
[arr[i], arr[j]] = [arr[j], arr[i]];
i++;
}
}

[arr[i], arr[right]] = [arr[right], arr[i]];

return i;
};

/**
* 퀵 정렬 (Quick Sort)
* 배열을 직접 수정해 정렬합니다.
*
* @param {number[]} arr - 정렬할 배열
* @param {number} [left=0]
* @param {number} [right=arr.length - 1]
* @returns {number[]} 정렬된 배열(원본 수정)
*/
export const quickSort = (arr, left = 0, right = arr.length - 1) => {
if (left >= right) return arr;

const pivotIndex = partition(arr, left, right);

quickSort(arr, left, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, right);

return arr;
};

/** ----------------------------------------------
* Tree Sort (추가 구현)
* Binary Search Tree 기반 정렬
* 새로운 배열 반환
* ----------------------------------------------*/
/**
* BST 노드 구조
*/
class TreeNode {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}

/**
* BST 삽입 함수
*
* @param {TreeNode|null} root - 루트 노드
* @param {number} value - 삽입할 값
* @returns {TreeNode}
*/
const insertNode = (root, value) => {
if (root === null) return new TreeNode(value);

if (value < root.value) root.left = insertNode(root.left, value);
else root.right = insertNode(root.right, value);

return root;
};

/**
* 중위 순회로 트리의 값을 오름차순 배열에 삽입하는 함수
*
* @param {TreeNode|null} node
* @param {number[]} res
*/
const inorderTraversal = (node, res) => {
if (!node) return;
inorderTraversal(node.left, res);
res.push(node.value);
inorderTraversal(node.right, res);
};

/**
* 트리 정렬 (Tree Sort)
* BST를 이용해 새로운 정렬된 배열을 반환합니다.
*
* @param {number[]} arr
* @returns {number[]} 정렬된 새 배열
*/
export const treeSort = (arr) => {
let root = null;

for (const value of arr) {
root = insertNode(root, value);
}

const res = [];
inorderTraversal(root, res);
return res;
};
Loading