2. 알고리즘
• 계산을 위한 “단계별” 절차
• 입력/출력
• 간단하고 명료
• 유한한 단계
• 실행 가능한 절차
3. 알고리즘 분석
• 점근적(asymptotic) 분석
• 함수의 상한과 하한에 대한 분석
!
• 항들 중 과 두 항은 n이 매우 큰 수가 되면 중요하지 않게 됨
• f(n)를 점근적으로 와 동등하다고 함
• 빅오(big-Oh), 빅 오메가(big-Omega), 빅 쎄타(big-Theta)
f(n) = n3
+ 20n2
+ 10n
20n2 10n
n3
f(n) = O(g(n) : f is bounded above by g
f(n) = ⌦(g(n)) : f is bounded below by g
f(n) = ⇥(g(n)) : f is bounded both above and below by g
상한
하한
4. 기초적 자료 구조
- 배열과 링크드 리스트
• 배열과 링크드 리스트의 장단비교
• 임의 접근 (시간)
• 배열이 나음
• 메모리 효율 (공간)
• 링크드 리스트가 나음
5. 링크드 리스트 구조
• 단일 연결 리스트(singly linked)
• 1 노드에 1 링크 (next)
• 이중 연결 리스트(doubly linked)
• 1 노드에 2개 링크 (prev. 와 next)
• 공통적으로 사용되는 자료
• head와 tail 포인터
6. 기초적인 자료 구조
- 스택
• 스택
• 후입선출(Last in, First out)
• 자료
• top: 최근 삽입 데이터의 인덱스
• array: stack에 담긴 자료
• 연산
• push: 데이터 추가
• pop: 데이터 제거
7. 기초적인 자료 구조
- 큐(QUEUE)
• 큐
• 선입선출(First in, First out)
• 데이터
• front, rear: 인덱스
• array: 큐에 담긴 데이터
• 연산
• add: 데이터 추가
• remove: 데이터 제거
rear
add remove
8. 기초적인 자료 구조
- 트리
• 그래프 G = {V, E}
• 정점집합 V와 간선집합 E의 집합
!
!
• 트리(tree)
• 사이클이 없는 그래프(acyclic graph)
10. 계층적 트리
• 1 개의 루트 노드
• 각 노드는 복수의 자식을 가질 수 있음
• n = 최대 자식 개수
• n-ary 트리
• 이진 트리(binary tree)
• 최대 자식 개수 = 2
• 레벨, 높이…
레벨 1
레벨 2
레벨 3
노드 10의 높이 = 2
루트 노드의 높이 = 트리의 높이
11. 정렬 - 선택정렬
• 리스트 L = { 정렬된 부분리스트 L(+), 정렬되지 않은 부분리스트 L(-) }
• 초기화: L = L(+)L(-)
• L(+) = nil
• L(-) = L
• 루프
• L(-)에서 가장 작은 값을 가진 “min”을 찾고, 이 “min”과 L(-)에서
가장 앞에 있는 원소의 자리를 바꾼다
• L(-)의 첫 원소를 L(-)에서 제거하고 L(+)에 넣는다
• L(+)=L이 될 때까지 루프를 반복한다.
L(+)
L(-)
12. 정렬 - 거품정렬
• 리스트 L = { 정렬된 부분 L(+), 정렬되지 않은 부분 L(-) }
• 초기화: L = L(-)L(+)
• L(-) = L
• L(+) = nil
• 루프:
• L(-)의 왼쪽에서 오른쪽으로
• 인접한 두 개의 원소를 비교하여 큰 것이 오른
쪽에 놓이도록 만든다
• 가장 큰 원소가 L(-)의 오른쪽 끝에 놓이게 된
다
• L(-)의 가장 오른쪽 끝 원소를 L(+)에 넣는다
• L(+)=L이 될 때까지 루프를 반복한다
L(-) L(+) = 0
max will be here
L(-) L(-)
compare
compare
compare
...
13. 정렬 - 삽입정렬
• 리스트 L = { 정렬된 부분 L(+), 정렬되지 않은 부분 L(-) }
• 초기화: L = L(+)L(-)
• L(+) = nil
• L(-) = L
• 루프
• L(-)에서 첫 번째 원소 x를 선택한다
• 이 원소 x가 놓을 위치를 L(+)에서 찾는다
• 해당 위치에 x를 삽입하고 x이후의 L(+)는 뒤로 한 칸씩 민다
• L(+)=L이 될 때까지 루프를 반복한다
14. 어떤 정렬이 좋은 정렬인가?
• 지금까지의 방법들 - 평균적 시간 복잡도
!
• 거의 정렬된 데이터는?
• 삽입정렬이 더 나음
• 왜?
• “적절한 위치”를 쉽게(적은 비교로) 찾을 수 있음
• 많은 경우
• 거의 정렬된 리스트가 주어짐 (충돌 처리…)
• 삽입 정렬이 거품정렬보다 좋다
• http://http.developer.nvidia.com/GPUGems3/elementLinks/32fig01.jpg
O(n2
)
15. 퀵 정렬(QUICK SORT)
더 빠른 정렬?
• 퀵 정렬
• 리스트 L을 정렬하려고 한다
• 피벗(pivot): L에 있는 어떤 한 원소
• L(-): 리스트에서 피벗보다 작은 원소들로 구성된 부분
• L(+): 리스트에서 피벗보다 큰 원소들로 구성된 부분
• 퀵 정렬 알고리즘
• L에서 x를 선택한다
• L을 L(-)와 x, 그리고 L(+)로 나눈다
• L(-)과 L(+)에 재귀적으로 퀵 정렬 함수를 호출한다
16. 퀵(QUICK) 정렬은 얼마나 ‘퀵’할까?
• 운이 좋은 경우
• 피벗이 리스트를 균등하게 쪼갠다
• 재귀호출의 깊이 = lgn
• 재귀호출 트리의 각 단계(level)에서 O(n) 작업이 필요
• 전체적인 시간 복잡도 =
• 운이 나쁜 경우 (예: 이미 정렬된 데이터)
• 피벗이 최소 혹은 최대 값을 가질 수 있음
• O(n) 재귀 호출
• 전체적인 시간 복잡도
• 평균: O(n lg n)
O(n lg n)
O(n2
)
17. 병합 정렬
-보장된 계산복잡도
• 알고리즘
• 루프 1
• 리스트를 반으로 쪼갠다
• 모든 리스트가 더이상 쪼개질 수 없을 때까지 루프 1 반복
• 루프 2
• 인접한 두 리스트를 병합하여 더 큰 정렬리스트를 만든다
• 모두 병합되어 하나의 리스트가 될 때까지 루프 2 반복
O(n lg n)
18. 탐색(SEARCH)
• 순차(sequential) 탐색
• O(n)
• 좀 더 효율적인 방법 필요
• 자기 조직화(self-organising) 리스트
• 자주 접근되는 원소를 리스트의 앞으로 옮겨 놓음
• 언제나 운이 좋지는 않을 것이다
19. 이진 탐색(BINARY SEARCH)
• 규칙
• 찾으려는 키: k, 검색을 하려는 대상은 정렬된 배열 array
• 위치 i의 값이 v라는 것을 알 수 있다: array[i] = v
• k=v이면 키를 발견했고 위치는 i가 됨
• k>v라면 array[i]보다 왼쪽 영역은 더이상 고려할 필요 없음
• k<v라면 오른쪽이 고려할 필요가 없어짐
• 알고리즘
• 1. 키 k와 리스트의 가운데 원소를 비교한다
• 2.
• 일치하면 가운데 원소의 인덱스를 리턴 (종료)
• 일치하지 않으면 왼쪽, 오른쪽 가운데 한 쪽을 규칙에 따라 버린다
• 3. 리스트가 남아 있다면 다시 1로 돌아간다
20. 이진 탐색 트리
(BINARY SEARCH TREE)
• 노드에 적용되는 간단한 규칙
• 나의 왼쪽 부트리(subtree)에 있는 모든 원소는 나보다 작은 값
• 나의 오른쪽 부트리(subtree)에 있는 모든 원소는 나보다 큰 값
• 작업
• 운이 좋을 때 (트리가 균형잡혀 있을 때)
• 탐색: O(lgn)
• 노드 추가: O(lgn)
• 삭제 (다음 슬라이드 상세 설명)
• 사소한 경우
• 잎(leaf)를 지우거나 하나의 부트리(subtree)를 가진 노드를 지울 때
• 사소하지 않은 경우
• 지울 노드의 왼쪽 부트리에서 제일 큰 원소 혹은 오른쪽 부트리에서 제일 작은 원소와 교체
21. 이진탐색트리 노드 삭제
• 사소한 경우
• 잎 노드인 경우
• 그냥 지우면 됨
• 내부 노드이지만 사소한 경우
• 가진 부트리가 하나인 경우
• 지울 노드의 부모와 자식을 연결해 줌
• 사소하지 않은 경우
• 지우려는 노드 x가 두 개의 부트리를 가지는 경우
• 오른쪽 부트리에서 가작 작은 원소 ‘min’을 찾음
• ‘min’을 x에 복사함
• 재귀적으로 원래의 ‘min’을 삭제하는 작업을 수행
22. 2-3-4 트리
• 왜 필요한가
• BST는 균형이 잡히지 않을 수 있음
• 어떻게 균형을 잡을 것인가? 답: 2-3-4 트리
• 노드의 종류 = 3 종
• 2 노드
• 1개 키와 2 개의 링크 (이진 트리 노드와 동일)
• 3 노드
• 2개의 키와 3 개의 링크
• 4 노드
• 3개의 키와 4 개의 링크 Patrick Prosser, 2-3-4 trees and red-black tree, course slide,
http://www.dcs.gla.ac.uk/~pat/52233/slides/234_RB_trees1x1.pdf
23. 2-3-4 트리: 어떻게 동작하나
• BST와 같은 방식으로 잎 노드를 찾는다
• 삽입시 대상 노드가 2-, 3- 노드인 경우 각각을 3-,4- 노드
로 키워서 새 아이템 삽입
• 잎 노드가 4 노드라면?
• 4-노드를 쪼개어 두 개의 2 노드를 만든다
• 가운데 원소를 위로 올린다
• 새 노드를 추가한다
• 4노드 분할이 연쇄적으로 일어날 수도?
• 잎 노드를 찾아 내려가면서 4-노드가 발견되면 미리
쪼갬
• 노드 삭제: 다소 복잡
2-3-4 트리는 균형잡힌 트리
O(lg n) 탐색이 언제나 가능
Patrick Prosser, 2-3-4 trees and red-black tree, course slide,
http://www.dcs.gla.ac.uk/~pat/52233/slides/234_RB_trees1x1.pdf
24. 흑적(RED-BLACK) 트리
• 2-3-4 트리의 문제: 각각의 노드가 서로 다른 구조를 가짐
• 더 나은 구현법
• 흑적 트리 - 모든 노드는 이진트리 노드, 간선은 흑, 적 두 종류
• 2-노드
• 3-노드
• 4-노드
붉은 간선이 상하로 두 개 연속 나타날 수는 없다
(따라서, 검은 간선의 수는 언제나 균형이 잡혀 있다)
Patrick Prosser, 2-3-4 trees and red-black tree, course slide,
http://www.dcs.gla.ac.uk/~pat/52233/slides/234_RB_trees1x1.pdf
제한조건
25. 흑적 트리
• 삽입
• 2진 탐색 트리처럼 새 아이템을 삽입할 위치를 찾는다
• 새 아이템이 달리게 되는 부모 노드에서 새 노드로 오는 간선을 붉은 색으로 칠한다
• 연속적으로 붉은 간선이 나타날 수 없다는 규칙을 지킨다
• 실제 삽입시 발생하는 경우들
right rotation left rotation left-right double rotation right-left double rotation
승진규칙(promotion rule)
부모 노드 p로 들어오는 간선과 p의 형제 노드로 들어오는 간선이 모두 붉은 색이라면
이들 간선을 검정으로 바꾸고, 할아버지 노드로 들어오는 간선을 붉은 색으로 바꾼다.
Patrick Prosser, 2-3-4 trees and red-black tree, course slide,
http://www.dcs.gla.ac.uk/~pat/52233/slides/234_RB_trees1x1.pdf
26. 우선 순위 큐 - HEAP
• 종류
• 맥스 힙(max-heap): 어떤 노드 x 아래의 모든 노드는 이 x보다 크다
• 민-힙(min-heap): 어떤 노드 x 아래의 모든 노느는 이 x보다 작다
• 힙(heap)은 완전이진트리
• 언제나 균형잡힌 트리
• 배열로 구현 가능
• i-번째 노드
• 자식: 2*i 번째와 2*i+1 번째
• 부모: i
2
⌫
29. 해시(HASH)
• 해시 함수
• 임의 크기를 가진 데이터를 고정된 크기의 데이터로 매핑(mapping)하는 함수로서 입력 데이터가 조금만 달라져도
출력 데이터는 상당히 큰 차이가 나야 한다 (Wikipedia, http://en.wikipedia.org/wiki/Hash_function)
• 이 함수는 일반적으로 역함수가 없는 함수이다.
• 해시 테이블
• data 는 hash(data)-th 번째 원소로 해시 테이블에 저장된다
• 충돌
• 해시 함수가 완전하지 않음
• 해법
• 체이닝
• 개방 주소형
• 선형 탐사, 제곱 탐사, 이중 해싱, 임의 주소
30. 해시 함수들
• 해시 함수의 예
• 곱셈법
!
• Knuth의 제안
!
• 나눗셈법: hash(k) = k mod m
• 제곱의 가운데
• 입력된 값을 제곱한 의 가운데 p-비트를 사용
• 폴딩
• 입력 키를 몇 개의 조각으로 나누어 더하거나 뒤집는 방식으로 하나로 합침
0 hash(k) < m
k2
A =
p
5 1
2
hash(k) = m · (k · A bk · Ac)
황금비율
31. 그래프(GRAPH)
• 그래프 G = {V,E}
• V: 정점의 집합
• E: 두 정점을 연결하는 간선의 집합
• 인접
• 두 노드가 간선으로 연결되어 있으면 두 노드가 인접하다라고 함
• 그래프를 표현하는 자료구조
• 인접 행렬, 인접 리스트
• 그래프의 종류
• 유향과 무향 그래프
• 가중치가 있는 것과 없는 것
undirected vs. directed
weighted vs. non-weighted
32. 그래프 순회(TRAVERSAL)
• 깊이 우선 탐색(DFS, depth-first-search)과 너비 우선 탐색 (BFS, breadth-first-search)
• DFS와 BFS는 각각 스택과 큐를 활용
A
B
C
D
E
F
G
H
I
DFS
Stack
[A] [AB] [ABC] [AB] [ABD] [ABDE] [ABDEF] [ABDE] [ABDEG] [ABDEGH] [ABDEG] [ABDGI]
Traversal: A, B, C, D, E, F, G, H, I
BFS
Queue
Traversal: A, B, C, D, E, G, F, H, I
[A] [B] [CD] [D] [EGH] [GHF] [HFI]
A
B
C
D
E
F
G
H
I
A
B
C
D
E
F
G
H I
DFS tree
BFS tree
33. 최소비용 신장 트리
(MINIMUM COST SPANNING TREE)
• 탐욕 기법
• 프림의 기법
• 두 개의 정점 집합을 준비: V, U
• v0 노드를 선택하고 V={v0}로 설정
• U = { 다른 모든 정점}
• V와 U를 연결하는 최소비용 간선 (v in V, u in U)를 찾는다
• 싸이클이 만들어지지 않으면 u를 V에 넣는다
• 크루스칼(Kruskal’s) 알고리즘
• 간선의 리스트를 비용에 따라 정렬한다.
• 간선을 오름차순으로 선택하여 스패닝 트리에 포함
• 싸이클을 만들면 포기
34. 다익스트라(DIJKSTRA)의 최단경로
• 하나의 시작점 - 모든 지점으로의 경로
subgraph with vertices of which shortest path was found
subgraph with vertices of which shortes paths are not known yet
G+
G
start
u : newly added vertex
d+
= 0
d+
u : found
v1
v2
vn
...
c1
c2
cn
dv2
dv1
dvn
initialisation
d+
start = 0 dvi
= 1
G+
= start
G = G start
u = start
Loop
d+
u + ci < dvi
) dvi
d+
u + ci
for all i
find minimum dv in G
add v into G+
, remove it from G
fix dv to be d+
v
u v
While G is not empty
35. 문자열 탐색
라빈 카프(RABIN-KARP) 기법
• 라빈-카프
• T: m 개의 글자를 가진 텍스트
• p: n 개의 글자를 가진 text
• h = hash(p)
• hi: T[i]에서 시작하는 n 개 글자의 해시값
• h = hi이면, 문자열 “T[i]…T[i+n-1]”가 p일 수 있음
• i=0 에서 m-n까지 검사 수행
• 해쉬
hi =
n 1X
j=0
T[i + j] · 2n 1 j
hi+1 = hi T[i] · 2n 1
+ T[i + n]
abcdefghijklmnopqrstuvwxyz
hash value = h1
hash value = h2
h2 = h1 b · 210
+ m
36. 문자열 탐색
KMP(KNUTH-MORRIS-PRATT) 기법
text
pattern mismatch
1 character shift
naive approach
text
pattern mismatch
jump to the mismatched location?
we want...
ANY PROBLEM?
Sometimes we cannot jump that far... Why?
text
pattern mismatch
identical
”Jump Table” is required
border
37. 문자열 탐색
보이어-무어(BOYER-MOORE) 기법
• 오른쪽에서 왼쪽으로 검사
• 나쁜 캐릭터 이동
• 좋은 접미부 이동
text
pattern
mismatch
comparison direction
bad character
bad character shift
text
pattern
mismatch
comparison direction
good su x
case 1
case 2
good su x is found in the left
su x of good su x matches the prefix of pattern
38. 동적계획법(DYNAMIC PROGRAMMING)
최장 공통 부분서열
(LONGEST COMMON SUBSEQUENCE)
• 부분서열(subsequence)
• 다른 서열의 원소들이 가진 순서를 변경하지 않고 일부 원소를 삭제함으로서 얻을 수 있는 서열
• 공통 부분서열
• 만약 G가 X의 부분서열이면서 동시에 Y의 부분서열이라면 G는 X와 Y의 공통 부분서열이다.
• 최장 공통 부분서열
• 최적 부분구조
Xi =< x1, x2, · · · , xi >
Yj =< y1, y2, · · · , yj >
|LCS(Xi, Yi)| =
0
@
0 , if i = 0 or j = 0
|LCS(Xi 1, Yj 1)| + 1 , if xi = yj
max(|LCS(Xi 1, Yj)|, |LCS(Xi, Yj 1)|) , if xi 6= yj and i, j > 0
1
A
39. 문제 해결 기법들
• 분할 정복(divide and conquer)
• 퀵 정렬, 합병 정렬
• 탐욕 기법
• 최적 부분 구조
• 최소비용 신장 트리
• 구현이 쉽다. 탐욕 기법으로 풀 수 있는지를 증명해야 함
• 동적 계획법
• 최적 부분 구조
• 큰 문제를 작고 쉬운 문제로 쪼개의 풀어 그 결과를 활용하여 큰 문제의 해를 구함