Skip to content
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
7 changes: 7 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"printWidth": 80
}
89 changes: 89 additions & 0 deletions algorithm/BinarySearchTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
class Node {
constructor(value) {
this.value = value;
this.left = null;
this.right = null;
}
}

class BinarySearchTree {
constructor() {
this.root = null;
}

insert(value) {
const newNode = new Node(value);
if (this.root === null) {
this.root = newNode;
return;
}

let current = this.root;
while (true) {
if (value < current.value) {
if (current.left === null) {
current.left = newNode;
return;
}
current = current.left;
} else {
if (current.right === null) {
current.right = newNode;
return;
}
current = current.right;
}
}
}

find(value) {
let current = this.root;
while (current !== null) {
if (value === current.value) return current;
current = value < current.value ? current.left : current.right;
}
return null;
}

remove(value) {
this.root = this._removeNode(this.root, value);
}

_removeNode(node, value) {
if (node === null) return null;

if (value < node.value) {
node.left = this._removeNode(node.left, value);
} else if (value > node.value) {
node.right = this._removeNode(node.right, value);
} else {
// 자식이 없는 경우
if (node.left === null && node.right === null) return null;
// 자식이 하나인 경우
if (node.left === null) return node.right;
if (node.right === null) return node.left;
// 자식이 둘인 경우 오른쪽 서브트리의 최솟값(inorder successor)으로 대체
let successor = node.right;
while (successor.left !== null) {
successor = successor.left;
}
node.value = successor.value;
node.right = this._removeNode(node.right, successor.value);
}
return node;
}
}

const bst = new BinarySearchTree();
bst.insert(10);
bst.insert(5);
bst.insert(15);
bst.insert(3);
bst.insert(7);

console.log(bst.find(7).value); // 7
console.log(bst.find(99)); // null

bst.remove(5);
console.log(bst.find(5)); // null
console.log(bst.find(7).value); // 7 (여전히 존재)
99 changes: 99 additions & 0 deletions algorithm/DoublyLinkedList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
class Node {
constructor(value) {
this.value = value;
this.next = null;
this.prev = null;
}
}

class DoublyLinkedList {
constructor() {
this.head = null;
this.tail = null;
}

addToHead(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
} else {
newNode.next = this.head;
this.head.prev = newNode;
this.head = newNode;
}
}

addToTail(value) {
const newNode = new Node(value);
if (this.tail === null) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
newNode.prev = this.tail;
this.tail = newNode;
}
}

findNode(value) {
let current = this.head;
while (current !== null) {
if (current.value === value) return current;
current = current.next;
}
return null;
}

insertAfter(targetValue, newValue) {
const targetNode = this.findNode(targetValue);
if (targetNode === null) return;

const newNode = new Node(newValue);

if (targetNode === this.tail) {
this.tail.next = newNode;
newNode.prev = this.tail;
this.tail = newNode;
} else {
newNode.next = targetNode.next;
newNode.prev = targetNode;
targetNode.next.prev = newNode;
targetNode.next = newNode;
}
}

removeNode(value) {
const nodeToRemove = this.findNode(value);
if (nodeToRemove === null) return;

if (nodeToRemove === this.head && nodeToRemove === this.tail) {
this.head = null;
this.tail = null;
} else if (nodeToRemove === this.head) {
this.head = this.head.next;
if (this.head) this.head.prev = null;
} else if (nodeToRemove === this.tail) {
this.tail = this.tail.prev;
if (this.tail) this.tail.next = null;
} else {
nodeToRemove.prev.next = nodeToRemove.next;
nodeToRemove.next.prev = nodeToRemove.prev;
}
}
}

const list = new DoublyLinkedList();
list.addToTail(1);
list.addToTail(2);
list.addToTail(3);
list.addToHead(0);

console.log(list.findNode(2).value); // 2
console.log(list.findNode(2).prev.value); // 1

list.insertAfter(2, 2.5);
console.log(list.findNode(2).next.value); // 2.5

list.removeNode(2.5);
console.log(list.findNode(2).next.value); // 3
71 changes: 71 additions & 0 deletions algorithm/LinkedList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}

class LinkedList {
constructor() {
this.head = null;
this.tail = null;
}

addNode(value) {
const newNode = new Node(value);
if (this.head === null) {
this.head = newNode;
this.tail = newNode;
} else {
this.tail.next = newNode;
this.tail = newNode;
}
}

findNode(value) {
let current = this.head;
while (current !== null) {
if (current.value === value) return current;
current = current.next;
}
return null;
}

insertAfter(targetValue, newValue) {
const targetNode = this.findNode(targetValue);
if (targetNode === null) return;

const newNode = new Node(newValue);
newNode.next = targetNode.next;
targetNode.next = newNode;

if (targetNode === this.tail) {
this.tail = newNode;
}
}

removeAfter(targetValue) {
const targetNode = this.findNode(targetValue);
if (targetNode === null || targetNode.next === null) return;

const nodeToRemove = targetNode.next;
targetNode.next = nodeToRemove.next;

if (nodeToRemove === this.tail) {
this.tail = targetNode;
}
}
}

const list = new LinkedList();
list.addNode(1);
list.addNode(2);
list.addNode(3);

console.log(list.findNode(2)); // Node { value: 2, next: Node { value: 3, ... } }

list.insertAfter(2, 2.5);
console.log(list.findNode(2).next.value); // 2.5

list.removeAfter(2);
console.log(list.findNode(2).next.value); // 3
58 changes: 58 additions & 0 deletions algorithm/Queue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
class Node {
constructor(value) {
this.value = value;
this.next = null;
}
}

class Queue {
constructor() {
this.front = null;
this.rear = null;
}

isEmpty() {
return this.front === null;
}

enqueue(value) {
const newNode = new Node(value);
if (this.isEmpty()) {
this.front = newNode;
this.rear = newNode;
} else {
this.rear.next = newNode;
this.rear = newNode;
}
}
dequeue() {
if (this.isEmpty()) return null;

const value = this.front.value;
if (this.front === this.rear) {
this.front = null;
this.rear = null;
} else {
this.front = this.front.next;
}
return value;
}

peek() {
return this.isEmpty() ? null : this.front.value;
}
}

const q = new Queue();
console.log(q.isEmpty()); // true

q.enqueue("A");
q.enqueue("B");
q.enqueue("C");

console.log(q.peek()); // A
console.log(q.dequeue()); // A
console.log(q.dequeue()); // B
console.log(q.isEmpty()); // false
console.log(q.dequeue()); // C
console.log(q.isEmpty()); // true
34 changes: 34 additions & 0 deletions algorithm/Sorts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
function heapsort(arr) {
const n = arr.length;

for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
heapify(arr, n, i);
}

for (let i = n - 1; i > 0; i--) {
[arr[0], arr[i]] = [arr[i], arr[0]];
heapify(arr, i, 0);
}
}

function heapify(arr, size, rootIndex) {
let largest = rootIndex;
const left = 2 * rootIndex + 1;
const right = 2 * rootIndex + 2;

if (left < size && arr[left] > arr[largest]) largest = left;
if (right < size && arr[right] > arr[largest]) largest = right;

if (largest !== rootIndex) {
[arr[rootIndex], arr[largest]] = [arr[largest], arr[rootIndex]];
heapify(arr, size, largest);
}
}

const arr1 = [3, 1, 4, 1, 5, 9, 2, 6];
heapsort(arr1);
console.log(arr1); // [1, 1, 2, 3, 4, 5, 6, 9]

const arr2 = [10, -3, 0, 7, -1];
heapsort(arr2);
console.log(arr2); // [-3, -1, 0, 7, 10]
Loading