HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
📝
학습 TIL
/
📝
5일차 배운 것 정리 (1)
📝

5일차 배운 것 정리 (1)

대주제
자료구조
작성완료
작성완료
전날 정리 노트 이동
다음 정리 노트 이동
주제
트리와 힙
트라이 자료구조
정렬
이진탐색
날짜
Mar 25, 2022

이전 내용

자료구조와 알고리즘 목차
  • 1. 자료구조와 알고리즘이 중요한 이유
  • 2. 자료구조의 종류 (완료)
  • 3. 시간복잡도
  • 4. 배열
  • 5. 연결리스트
  • 6. 스택
  • 7. 큐
  • 8.해시테이블
  • 9.그래프
 
 

목차
이전 내용10.트리11. 힙(Heap)12.트라이 (Trie)13. 정렬정렬의 특징정렬알고리즘 종류14. 이진 탐색 (Binary Search)실습(입국심사)

10.트리

방향그래프의 일종으로 정점이 가르키는 간선이 하나 밖에 없는 구조를 가진 비선형 자료구조
개념
  • 루트(Root)
    • 트리의 최상단에 있는 노드를 가르킴
  • 레벨(Level)
    • 루트노드로 부터 해당 노드까지의 깊이
  • 차수(degree)
    • 한 정점에서 뻗어나가는 간선의 숫자
notion image
사례
  • 조직도
  • 폴더구조
 
특징
  • 루트 노드를 제외한 모든 노드는 하나의 부모 노드를 가진다.
  • 루트에서 특정 정점으로 가는 경로는 유일하다.
 
이진트리
각 정점이 최대 2개의 자식을 가지는 트리를 의미
종류에 따라 편향이진트리 > 완전이진트리 > 포화이진트리 가 존재
 
이진트리의 특징
  • 편향트리(최악의경우) N개의 노드에서 높이가 N이 될 수 있다.
  • 정점이 N개일 때, 완전이진트리와 포화이진트리의 높이는 logN이다.
  • 주로 이진트리를 활용하여 다른 자료구조로 응용된다.
    • 이진탐색트리(BST)
    • 힙(Heap)
    • AVL트리
    • 레드블랙트리
 
이진 트리의 구현
  • 이진트리에서 index 구하는 방법
    • left: index * 2
    • right : index * 2 + 1
    • 부모 : 현재 index / 2 후 소수점버림
    • 배열방식
      인접리스트 방식
 
전위순회, 중위순회, 후위순회를 구현하기
전위 순회
중위 순회
후위 순회

11. 힙(Heap)

우선순위 큐 (자료구조가 아닌 개념이다)
FIFO인 큐와 달리 우선순위가 높은 요소가 먼저 나가는 큐
 
다양한 방법으로 구현 가능
  • 힙으로 구현 (우선순위큐 ≠힙)
    • 힙이란 -
힙의 특징
  • 1.
  • 2.
  • 3. js에서는 직접 구현
 
힙의 동작원리
요소추가 (O(logN))
  • 1
  • 2
  • 3
요소 제거 ()
  • 루트에서만 요소제거
  • 루트 제거 시 마지막 정점이 루트로 위치
  • 루트 정점의 두 자식 정점과 비교&교환 반복 실시
js에서의 구현 (maxHeap)
요소추가
class MaxHeap(){ constructor(){ this.heap = [null] // 0번 idx 관리 쉽게 비어준다. } // 제일 뒤에 들어오고, 부모랑 비교&교체 반복 push(value){ this.heap.push(value); let currentIndex = this.heap.length - 1; // 추가된 요소의 idx let parentIndex = Math.floor(currentIndex / 2); // 부모값이 작으면 교체, 정점(parentIndex = 0)까지 반복 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 currentIndex = this.heap.length -1; const temp = this.heap this.heap.[1] = this.heap const }
요소제거
// 부모요소 제거 후, 마지막 정점 부모로 이동 // 정점이 각 자식과 비교하여, 현재노드가 자식노드 보다 작을 경우 교체 반복 pop() { const returnValue = this.heap[1]; this.heap[1] = this.heap.pop(); console.log(returnValue, this.heap); let currentIdx = 1; let leftIdx = 2; //Math.floor(currentIndex / 2); let rightIdx = 3; // leftIdx + 1; while ( this.heap[currentIdx] < this.heap[leftIdx] || this.heap[currentIdx] < this.heap[rightIdx] ) { // 왼쪽자식 오른쪽 자식과의 비교 (현재요소는 둘 중 하나보다 무조건 작음이 판정) if (this.heap[leftIdx] < this.heap[rightIdx]) { const temp = this.heap[currentIdx]; this.heap[currentIdx] = this.heap[rightIdx]; this.heap[rightIdx] = temp; currentIdx = rightIdx; } else { const temp = this.heap[currentIdx]; this.heap[currentIdx] = this.heap[leftIdx]; this.heap[leftIdx] = temp; currentIdx = leftIdx; } leftIdx = currentIdx * 2; rightIdx = currentIdx * 2 + 1; } console.log(this.heap); return returnValue; }
최소힙 구현(minHeap)
 

12.트라이 (Trie)

문자열을 저장하고, 효율적으로 탐색하기 위한 트리형태의 자료구조
검색 서비스에서의 자동완성 기능 어떻게 구현?
→ 트라이
notion image
트라이의 특징
  • 자동완성, 사전 찾기
  • 문자열 탐색,삽입 시 효율적 (O(L:문자열길이))
    • 단점: 정점이 자식에 대한 링크를 모두 가지고 있어야 해서 공간 많이 사용
 
트라이 생성
구조 ( 해시테이블 + 연결리스트 )
  • 루트는 비어 있다.
  • 각 간선은 추가될 문자를 키로 가진다.
  • 각 정점은 “이전 정점의 값 + 간선의 키” 를 값으로 가진다.
 
스텝 예시 (cat & can)
  • 빈 루트 정점
  • step1. 문자열 자르기
  • step2. 문자열 저장되어 있나 확인 (at 루트)
    • 1) 있다면, 해당 정점으로 이동
    • 2) 없다면, 루트 정점의 자식으로 추가
  • step3. 이후 정점에서의 문자열 저장 확인
    • 1) 있다면, 해당 정점으로 이동
    • 2) 없다면, 새로운 자식 정점 생성 (값: 현재 정점의 값 + 찾는 문자열 값)
 
js에서 트라이 구현
놓쳤던(어려웠던) 부분
  • children에 저장하는 data의 형식
    • Map() 자료구조로 저장 - key는 간선으로 문자열(char), value는 해당 Node
// 각 노드는 모든 자식 요소를 연결리스트 키-값으로 가지고 있는다. (Map) class Node { constructor(value = "") { this.value = value; this.children = new Map(); // key-value (char-node) } } class Trie { constructor() { this.root = new Node(); } // 해당 string이 분해되어 노드형식으로 저장이 된다. // 루트부터 시작하여, 타고 내려간다. insert(string) { let currentNode = this.root; for (const char of string) { if (currentNode.children.has(char)) { currentNode = currentNode.children.get(char); } else { currentNode.children.set(char, new Node(currentNode.value + char)); currentNode = currentNode.children.get(char); } } } // 현재 트라이가 해당 string을 가지고 있는지 판별한다. 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; } }
 
트라이를 이용한 자동완성 코드 구현 (과제)
  • hint: 트리파트의 레벨 순회 응용
    • trie에 있는 String: "str", "string", "star" 자동완성("st") 하면
      1. 출력: ["str", "string", "star"]

13. 정렬

정렬의 특징

  • 정렬 기준은 사용자가 정한다. (오름차순, 내림차순)
  • 비교식 정렬, 분산식 정렬로 나뉜다
  • 삽입, 선택, 버블, 머지 ,힙, 퀵 정렬등 다양한 정렬 방식 존재
가장빠른 정렬
  • 각각의 상황에 따라 다르다.

정렬알고리즘 종류

비교식정렬
1.버블정렬 (O(n^2))
서로 인접한 두 요소를 검사하는 정렬 알고리즘
  • n번 순회를 n-1번 수행
notion image
2.선택정렬(O(n^2)
선택한 요소와 가장 우선순위가 높은 요소를 교환하는 정렬 알고리즘
notion image
 
3.삽입정렬(O(n^2))
선택한 요소를 삽입할 수 있는 위치를 찾아 삽입하는 정렬 알고리즘
  • 어느정도 정렬이 되어 있다는 것이 보장 되면 퀵정렬 보다 빠르게 작동
 
 
분산식정렬
  • 핵심 아이디어
    • 분할 정복
      notion image
4.합병정렬(O(n * logn))
분할 정복 알고리즘을 이용한 정석적인 정렬 알고리즘
notion image
  • 최선과 최악이 같은 안정적인 정렬 알고리즘
  • Divide & Conquer 방식
 
5.퀵 정렬(O(n * logn))
분할 정복알고리즘을 이용하여 빠르지만, 최악의 경우가 존재하는 불안정 정렬
  • pivot을 이용한 정렬
notion image

14. 이진 탐색 (Binary Search)

↔ 선형탐색 :순차적으로 찾는 방법
이진탐색은 요소들이 정렬되어 있을 때,
 
이진탐색 특징
  • 반드시 정렬이 사전에 되어있어야한다.
  • O(log n) 으로 상당히 빠른 시간복잡도를 가진다.
  • 배열과 이진트리를 이용하여 구현
 
배열을 이용한 구현
  • mid (left + right)/2 값을 통해 찾기
    • notion image
  • 중간 요소 탐색 시 선형시간(O(n))이 걸리는 단점 → 이진탐색트리로 구현
 
이진탐색트리를 통한 구현
이진트리에서 하나의 규칙(정점을 기준으로 왼쪽 서브트리는 작은 값, 오른쪽 서브트리는 큰 값을 가진다)을 추가한 자료구조
  • 하나의 서브 트리를 가지는 경우
  • 두개의 서브 트리를 가지는 경우
문제점
  • 최악의 경우 한쪽으로 편향된 트리가 될 수 있다.
 
js에서의 구현 (by 배열)
const array = []; find
 
js에서의 구현 (by BST)
 

실습(입국심사)

  • O(n^2) 으로 효율성 실패
    • function solution(n, times) { var answer = 0; // [0,0,7,10, 14, 20, 21 ,28, 30] let t = []; for(let i = 1; i <= n; i++){ times.forEach(time => t.push(time * i)) } return t.sort((a,b)=> a-b)[n-1] }