알고리즘
10월 10, 2024·
·
5 분 읽기
안상아

1. 개요
알고리즘 과목은 데이터를 구조화하고 문제를 효율적으로 해결하기 위한 방법론을 학습한다. 아래 정리는 강의에서 다루는 대표 주제를 빠르게 복습하거나, 각 개념의 관계를 한눈에 파악하기 위해 구성되었다.
2. 정렬 알고리즘
정렬은 대부분의 문제 해결 과정에서 선행되어야 하는 기본 연산이다. 알고리즘 선택 시 입력 크기, 데이터 분포, 메모리 사용량, 안정성(안정 정렬 여부) 등을 고려한다.
| 알고리즘 | 평균 시간복잡도 | 최악 시간복잡도 | 추가 공간 | 특징 |
|---|---|---|---|---|
| 병합 정렬 (Merge Sort) | O(n log n) | O(n log n) | O(n) | 안정 정렬, 외부 정렬에 적합 |
| 퀵 정렬 (Quick Sort) | O(n log n) | O(n²) | O(log n) | 분할 정복, 피벗 선택이 핵심 |
| 선택 정렬 (Selection Sort) | O(n²) | O(n²) | O(1) | 교환 횟수가 적음, 불안정 |
| 버블 정렬 (Bubble Sort) | O(n²) | O(n²) | O(1) | 구현이 단순, 이미 정렬된 경우 빠름 |
| 삽입 정렬 (Insertion Sort) | O(n²) | O(n²) | O(1) | 부분적으로 정렬된 데이터에 효율적, 안정 |
| 기수 정렬 (Radix Sort) | O(d·n) | O(d·n) | O(n+k) | 자릿수 기반, 비교 연산 불필요 |
| 계수·버킷 정렬 (Counting/Bucket) | O(n+k) | O(n+k) | O(n+k) | 데이터 범위가 작거나 균등 분포일 때 강력 |
2.1 병합 정렬
- 분할 정복 패턴을 통해 배열을 절반씩 나누고, 정렬된 부분 배열을 병합한다.
- 안정 정렬이므로 동일 키의 상대적 순서가 유지된다.
- 단점: 추가 메모리 요구, 재귀 호출로 인한 오버헤드.
2.2 퀵 정렬
- 피벗을 기준으로 작은 값과 큰 값으로 파티셔닝 후 재귀 정렬.
- 평균적으로 가장 빠르지만, 이미 정렬된 데이터에서 최악의 O(n²)가 발생하므로 랜덤 피벗 선택, median-of-three 등의 기법을 활용한다.
2.3 선택 정렬
- 남아 있는 원소 중 최솟값(또는 최댓값)을 찾아 앞으로 보낸다.
- 교환 횟수가 O(n)으로 제한되지만 전반적으로 느려 교육용으로 주로 사용된다.
2.4 버블 정렬
- 인접한 두 원소를 비교하여 순서가 틀리면 교환한다.
- 패스마다 가장 큰 값이 뒤로 이동한다. 버전마다 조기 종료 플래그를 사용하면 부분 정렬된 데이터를 빠르게 처리 가능.
2.5 삽입 정렬
- 현재 원소를 이미 정렬된 구간에 삽입한다.
- 리스트 길이가 작거나 사실상 정렬된 상태라면 매우 효율적이며, 각 단계에서 안정성이 유지된다.
2.6 기수 정렬
- 정수나 고정 길이 문자열을 자릿수별로 정렬한다. LSD(Least Significant Digit) 방식은 낮은 자릿수부터, MSD(Most Significant Digit)는 높은 자릿수부터 처리한다.
- 내부적으로 안정 정렬(예: 계수 정렬)을 사용해야 전체 정렬의 안정성이 유지된다.
2.7 계수 정렬과 버킷 정렬
- 계수 정렬은 값의 범위 k가 작을 때 O(n+k)의 성능을 보장하고, 버킷 정렬은 입력이 균등 분포일 때 평균 O(n) 성능을 기대한다.
- 메모리 사용량이 크며, 실제 값의 범위를 사전에 알아야 한다.
3. 트리: 레드-블랙 트리
Balanced Binary Search Tree의 대표 구현 중 하나로, 삽입·삭제 후에도 높이가 O(log n)으로 유지되도록 색상 규칙을 적용한다.
- 불변 조건: (1) 각 노드는 빨강 또는 검정, (2) 루트·리프(NIL)는 검정, (3) 빨강 노드의 자식은 모두 검정, (4) 어떤 노드에서 리프까지 가는 모든 경로의 검정 노드 수 동일.
- 연산: 삽입은 이진 탐색 트리에 삽입 후 색 재조정과 회전을 수행한다. 삭제는 대체 노드 선택 후
double black문제를 해결하기 위해 추가 회전/재색. - 장점: AVL 트리보다 회전 횟수가 적어 삽입/삭제가 빈번한 환경에서 유리.
- 응용: STL의
std::map,std::set, Java의TreeMap, Linux Completely Fair Scheduler 등.
4. 해시 테이블
- 개념: 키를 해시 함수로 변환하여 배열 인덱스를 직접 접근함으로써 평균 O(1)의 탐색/삽입/삭제 성능을 목표로 하는 자료구조.
- 충돌(Collision): 다른 키가 같은 해시 버킷을 점유하는 현상. 해시 함수 품질과 로드 팩터(load factor = n / m)가 성능을 좌우한다.
4.1 충돌 해결 전략
- 체이닝(Separate Chaining): 같은 버킷에서 연결 리스트/동적 배열을 사용. 구현이 단순하며 확장이 유연하지만 추가 포인터 메모리가 필요.
- 개방 주소법(Open Addressing): 빈 버킷을 탐색해 데이터를 저장. 선형 조사(linear probing), 제곱 조사(quadratic probing), 이중 해싱(double hashing) 등이 있다. 캐시 친화적이지만 클러스터링 문제가 발생할 수 있다.
- 재해싱(Rehashing): 로드 팩터가 임계치를 넘으면 테이블 크기를 확장하고 모든 요소를 다시 해시한다.
4.2 설계 팁
- 좋은 해시 함수는 균등 분포, 계산 효율성, 의도적 공격에 대한 저항성을 갖춰야 한다.
- 동시성 환경에서는 락프리 해시, 세그먼트 락 등 추가 고려가 필요하다.
5. 그래프 알고리즘
그래프는 정점과 간선으로 구성된 추상화로, 네트워크, 경로 탐색, 위상 관계를 모델링한다. 구현 시 인접 리스트가 공간 효율적이며, 밀집 그래프는 인접 행렬이 연산을 단순화한다.
5.1 위상 정렬 (Topological Sort)
- 방향 비순환 그래프(DAG)의 선행 관계를 선형 순서로 나열한다.
- Kahn 알고리즘(진입 차수 0 큐)과 DFS 기반 알고리즘이 대표적. 순환이 존재하면 수행이 불가능하므로 검출 역할도 수행한다.
- 과목 선후수 관계, 빌드 시스템, 작업 스케줄링에 활용.
5.2 벨만-포드 알고리즘 (Bellman-Ford)
- 음수 가중치가 존재하는 그래프에서 단일 출발점 최단 경로를 구한다.
- 총 V-1회 간선 완화(relaxation)를 수행하며, V번째 완화에서 값이 갱신되면 음수 사이클이 존재함을 의미한다.
- Dijkstra가 적용되지 않는 네트워크 라우팅(RIP) 등에 필수.
5.3 페블 게임 (Pebble Game)
- DAG상의 노드에 조약돌(pebble)을 배치하면서 계산 순서를 분석하는 모델.
- 레지스터 할당, 메모리 최소화 문제, 증명 복잡도 등에서 필요한 자원 수의 하한을 유도할 때 사용한다.
- 목표는 목표 노드에 pebble을 올리기 위해 필요한 최소 pebble 수 또는 이동 횟수를 찾는 것. 동적 계획법, 탐욕 전략으로 표현 가능하지만 일반 그래프에서는 난이도가 높다.
5.4 기타 그래프 알고리즘 개요
- DFS/BFS: 탐색 기본기. 경로 유무, 컴포넌트, 위상 정렬의 토대.
- Strongly Connected Components (SCC): Kosaraju, Tarjan 알고리즘으로 DAG 축약 그래프 파악.
- 최소 신장 트리(MST): Kruskal, Prim 알고리즘. 네트워크 비용 최소화 문제의 기본.
6. 문자열 매칭: 라빈-카프 (Rabin-Karp)
- 롤링 해시를 이용해 패턴의 해시값과 텍스트 부분 문자열 해시값을 비교한다.
- O(n+m) 기대시간을 제공하며, 해시 충돌 발생 시 실제 문자열 비교로 검증한다.
- 여러 패턴을 동시에 검색할 때 패턴 해시를 미리 계산해두면 효율적이다.
7. 학습 팁
- 구현 연습 시 시간복잡도 분석과 함께 최악·평균 케이스 데이터를 직접 만들어 시험해 본다.
- 시각화 도구(VisuAlgo, CS Academy 등)로 단계별 동작을 확인하면 개념 이해가 빠르다.
- 실제 코딩 테스트에서는 공간 제한과 입력 범위를 먼저 파악해 적절한 알고리즘을 선택한다.
- 참고 교재: CLRS, Algorithms (Sedgewick), Problem Solving with Algorithms and Data Structures (Miller & Ranum).