오늘부터 과제제출이 시작되었다. 원래 계획은 빨리 강의와 TIL을 마무리하고 과제를 풀려고 했는데 알고리즘 문제를 풀고 힙을 완벽히 이해하는데 시간을 많이 쓰다 보니 벌써 7시가 되었다. 코어타임 이후에 조금씩 시도해봐야겠다. 공부하면서 코드가 이해가지 않을 때, 값들을 넣어가면서 노트에 적으면서 하니 훨씬 재밌고 이해하기도 쉬웠다. 힙 은근 재밌을지도?😁😁 바꾼 방식대로 TIL을 간단하게 작성하는게 블로그 작성 시간을 줄이는데 도움이 많이 된다. 물론 연결리스트를 활용한 이진트리는 과제를 하면서 보충해야할 것 같다. 내일도 화이팅🔥🔥
= 방향 그래프의 일종으로 정점을 가리키는 간선이 하나밖에 없는 구조를 가지고 있다.
예시) 조직도, 컴퓨터 디렉토리 구조
FIFO인 큐와 달리 우선순위가 높은 요소가 먼저 나가는 큐
💡 우선 순위 큐는 자료구조가 아닌 개념이다.
우선순위큐를 구현하는 방법에는 여러가지가 있는데 힙이 가장 적합하다.
= 이진 트리 형태를 가지며 우선순위가 높은 요소가 먼저 나가기 위해 요소가 삽입, 삭제 될 때 바로 정렬되는 특징이 있다.
class MaxHeap {
constructor() {
this.heap = [null];
}
push(value) {
this.heap.push(value);
let currentIndex = this.heap.length - 1;
let parentIndex = Math.floor(currentIndex / 2);
while (parentIndex !== 0 && this.heap[parentIndex] < value) {
const temp = this.heap[parentIndex];
this.heap[parentIndex] = value;
this.heap[currentIndex] = temp;
currentIndex = parentIndex;
parentIndex = Math.floor(currentIndex / 2);
}
}
pop() {
const returnValue = this.heap[1];
this.heap[1] = this.heap.pop(); //가장 마지막 정점이 루트로 올라온다.
let currentIndex = 1;
let leftIndex = 2;
let rightIndex = 3;
//루트 값이 자식 정점보다 작을때
while (this.heap[currentIndex] < this.heap[leftIndex] || this.heap[currentIndex] < this.heap[rightIndex]) {
if (this.heap[leftIndex] < this.heap[rightIndex]) {
//오른쪽 정점이 왼쪽 정점보다 더 클 때
const temp = this.heap[currentIndex]; //루트
this.heap[currentIndex] = this.heap[rightIndex];
this.heap[rightIndex] = temp;
currentIndex = rightIndex;
} else {
//왼쪽 정점이 오른쪽 정점보다 더 클 때
const temp = this.heap[currentIndex];
this.heap[currentIndex] = this.heap[leftIndex];
this.heap[leftIndex] = temp;
currentIndex = leftIndex;
}
leftIndex = currentIndex * 2;
rightIndex = currentIndex * 2 + 1;
}
return returnValue;
}
}
const heap = new MaxHeap();
heap.push(45);
heap.push(36);
heap.push(54);
heap.push(27);
heap.push(63);
console.log(heap.heap); //[null,63,54,45,27,36]
console.log(heap.pop());
console.log(heap.pop());
console.log(heap.pop());
console.log(heap.pop());
console.log(heap.pop());
문자열을 저장하고 효율적으로 탐색하기 위한 트리 형태의 자료구조
//안접리스트 형태로 구현
class Node {
//트리 구조이므로 노드 필요
constructor(value = "") {
this.value = value;
this.children = new Map();
}
}
class Trie {
//트라이 생성시 루트로 빈 노드 생성
constructor() {
this.root = new Node();
}
insert(string) {
let currentNode = this.root; //탐색을 위해 루트부터 시작
for (const char of string) {
if (!currentNode.children.has(char)) {
//자른 문자열의 값을 간선으로 갖고 있지 않는 경우 새롭게 노드 추가
currentNode.children.set(char, new Node(currentNode.value + char));
}
currentNode = currentNode.children.get(char); // 다음 정점으로 이동
console.log(currentNode);
}
}
has(string) { //문자열이 존재하는지 체크하는 함수
let currentNode = this.root;
for (const char of string) {
if (!currentNode.children.has(char)) {
return false;
}
currentNode = currentNode.children.get(char);
}
return true;
}
}
const trie = new Trie();
trie.insert("cat");
trie.insert("can");
console.log(trie.has("cat"));
console.log(trie.has("can"));
console.log(trie.has("cap"));
= 요소들을 일정한 순서대로 열거하는 알고리즘
💡 어떤 정렬이 제일 빠를까? 무엇이 더 좋고 나쁜지 정해져있진 않다.
다른 요소와 비교를 통해 정렬하는 방식
선택한 요소와 가장 우선순위가 높은 요소를 교환하는 정렬 알고리즘. O()
선택한 요소를 삽입 할 수 있는 위치를 찾아 삽입하는 방식의 정렬 알고리즘. O()
두번째 요소부터 시작된다. 비교해서 밀어내는 방식
어느정도 정렬되있다는 전제에서는 퀵정렬보다 빠르다
요소를 분산하여 정렬하는 방식
💡 분산식 정렬에 핵심적으로 쓰이는 전략: 분할 정복
문제를 작은 2개의 문제로 분리하고 더 이상 분리가 불가능 할 때 처리한 후 합치는 전략
분할 정복 알고리즘을 이용한 최선과 최악이 같은 안정적인 정렬 알고리즘. O(nlogn)
분할 정복 알고리즘을 이용한 매우 빠르지만 최악의 경우가 존재하는 불안정한 정렬. O(nlogn)
pivot을 기준으로 좌측(작은값들의 모임)과 우측(큰값들의 모임)으로 나눈다.
다시 나눈 배열에서 첫번째 요소가 pivot이 된다. 그리고 그 pivot을 기준으로 또 나눈다.
주의할점 : 그냥 sort()로 정렬할 경우 아스키 문자 순서로 정렬된다!
프로그래머스 데브코스 FE 강의