[강의정리] 알고리즘 Searching Methods


Search Problems

consist

  • A state space
  • A succeossor function

problem

  1. Initial state

Search Strategies

  1. Completeness
  • Solution을 찾을 수 있는가
  1. Optimality
  • 최소 코스트가 항상 나오는가
  1. Time complexity

  2. Space complexity

Uninformed Search Strategies

  • DFS
  • BFS
  • UNIFORM

[강의정리] 알고리즘 Backtracking, Branch-and-Bound


Depth First Search(깊이우선탐색)

  • 노드의 모든 후손노드를 방문한다. (preorder tree traversal)

State Space Tree(상태 공간 트리)

  • 뿌리 노드에서 잎노드까지의 경로가 해답후보(candidate solution)가 되는 트리
  • DFS를 하여 해답을 찾을 수 있음. 그러나 가능성이 없는 노드도 검색해서 비효율적

Back Tracking

  • 정의: promising

    • 전혀 해답이 나올 가능성이 없는 노드: (non-promising)
    • 그렇지 않은 노드: promising
  • 되추적?

    • 유망성 점검 후 유망하지 않으면, 부모노드로 돌아가서(“backtrack”) 다음 후손에 대한 검색을 진행

BackTracking 개념

  • 상태공간트리에서 깊이우선검색 실시
  • 유망하지 않으면 가지쳐서(pruning) 검색하지 않음
  • 유망한 노드만 자식노드 검색

The 0-1 Knapsack Problem

  • Optimization problem이므로 검색이 끝나기 전까진 해답을 알 수 없음

Let:

  • profit: 가치 총합
  • weight: 무게 총합
  • totweight: 무게 count
  • bound: 가치 추정치

풀이:

  • 단위당 가치가 높은 순으로 sort

    • 탐욕적 방법처럼 보이지만 탐욕적인 알고리즘은 아니다.
  • bound와 totweight를 profit과 weight값으로 초기화

  • 탐욕적으로 아이템 취하기

  • toweight이 W초과할때까지

  • 남은부분에 마지막일부취하고 profit을 bound에 더함

분석

  • 점검하는 마디의 수: O(2^n)

  • DP보다 좋은가? 확실하지 않음

    • DP worst(O(min(2^n, nW)))
    • BT worst(O(2^n))

Branch-and-Bound (분기한정법)

  • backtracking과 비슷

    • state space tree 사용
  • Backtracking과 차이점

    • 트리를 순회하는 방법을 제한하지 않는다.
    • 최적화 문제에서만 사용

Breadth-First Search ( 너비우선탐색)

  1. 뿌리마디 먼저 검색
  2. 다음 수준1에있는 모든 마디를 검색
  3. 다음 수준2에있는 모든 마디를 검색
  • Queue 사용

Best-First Search (최고우선탐색)

  • 최고의 한계를 가진 마디를 우선으로 선택
  • 우선순위 큐(Priority QUeue) 사용

The Travveling Salesperson Problem (TSP)

  • 외판원의 집이 위치하고 있는 도시에서 출발,
    다른 도시들을 각각 한번씩만 방문하고, 다시 집으로 돌아오는
    가장 짧은 일주여행경로(tour)을 결정하는 문제

  • 여러개의 징루 여행경로 중에서 길이가 최소가 되는 경로가 최적일주여행경로(optimal tour)가 된다.

  • 부르트포스 알고리즘:

    • 가능한 일주여행경로의 총 개수는 (n-1)!

DP를 이용한 접근방법

  • V: 모든 정점의 집합

  • A: V의 부분집합

  • D[vi][A]: A에 속한 각 정점을 한번씩만 거쳐서 vi에서 v1로 가는 최단경로 길이

  • D[vi][V-{v1}] = min(W[1][j] + D[vj][V-{v1, vj}])

  • n=40일때 DP로 6년…. O(n^2*s2^n)

분기한정법을 이용한 접근방법

상태공간트리 구축방법

  • 각 마디는 출발마디로부터 일주여행경로

  • 리프노드에있는 일주여행경로를 찾음

  • lowerbound 가져오기

Branch-and-Bound

  • Backtracking은 속해있다.

[강의정리] 알고리즘 기말정리


Minimum Spanning Tree

  • 정의
  • 알고리즘(Prim’s and Kruskal’s) complexities, 이게 greedy appraoch인가??

Dijkstra’s Algorithm for Single-Source Shortest Paths

  • 소스코드레벨 구현

Knapsack Problem (fractional & 0-1) 차이

  • Greedy approach로 Optimal(최적)한 Solution을 찾을 수 있는가? 어떨때 가능한가?
  • Greedy vs. Dynamic Programming
  • Backtracking & Branch-and-Bound
    • DPS, BPS, Best-First searches…
    • pruning

TSP (Traveling Salesperson Problem)

  • DP vs. Greedy? or Branch-and-Bound?
  • 유전 알고리즘, 다른것들과 차이, 장단점, 최적의 Solution을 가질 수 있는가?

Search Algorithms

  • Actual tree searches…

    • 방문하는 노드들 & 최적경로 ()
    • 방문 트리 구성
  • 장단점

  • 최적의 해를 찾는 보장은?

  • Complexities & 구현방법(data structures?)

[강의정리] 알고리즘 Nonlinear Unconstrained Optimization


Nonlinear Unconstrained Optimizations

  • Heuristic: 짐작, 경험등 규칙을 통하여 수행하는 알고리즘
  • Optimality: X

Genetic Algorithms (GE) : 유전 알고리즘

  • N개의 hypotheses(가설), 유지해나가는 알고리즘
  • 집단 유전학의 개체 진화 원리르 이용하는 문제해결공간 탐색 방법
  • In population:
    • Selection: 어떤것을 선택할것인가
    • Crossover: Selection한 후보중 어떤식으로 Mixable 할것인가
    • Mutation: 어떻게 변이를 줄건가
    • Replacement: 새로운 N개를 대치

유전알고리즘 표현

  • 순서 기반 표현: 각각의 노드들을 하나하나 index줘서 표현

선택 연산

  • 교차에 쓰이는 두개의 부모 해를 고르기 위한 연산
    • 우수한 해가 선택될 확률이 높아야함

품질 비례 룰렛휠 선택

  • 각 해의 품질을 평가한 다음 가장 좋은 해의 적합도가 가장 나쁜 해의 적합도의 k배가 되도록 조절
  • fi = (Cw - Ci) + ( Cw - Cb ) / (k - 1), k>1
    • Cw : 해집단 내에서 가장 나쁜 해의 비용
    • Cb : 해집단 내에서 가장 좋은 해의 비용
    • Ci : 해 i의 비용

순위기반 선택

  • 해잡단 내에서 해들을 품질 순으로 순위를 매긴 후 다음 가장 좋은 해부터 일차 함수적으로 적합도 배정
  • fi = max + ( i - 1 ) X (min - max ) / (n - 1)

교차 연산

  • 유전 알고리즘의 대표 연산
  • 연산 중 가장 다양한 대안 존재

일점 교차(point crossover)

  • 길이가 n인 일차원 문자열로된 염색체 상에서 일점 교차로 자르는 방법(총 n-1가지)

다점 교차(multipoint crossover)

  • 염색체의 길이가 n일 때 k점 교차로 자르는 방법의 총 수는 n-1Ck가지

  • 일점교차보다 교란의 정도가 커서 보다 넓은 탐색 공간을 탐색할 수 있음

  • 교란이 강하면 수렴성이 떨어져 주어진 시간 예산내에 제대로 수렴하지 않을 가능성

균등 교차(uniform crossover)

  • 자름선을 이용하지않음
  • 이론적으로 완벽(모든 재조합 가능성 open)
  • 난수를 사용

사이클 교차(cycle crossover)

  • 염색체가 순열일경우 사용
  • S2[index] = S1

순서 교차(order crossover)

  • 염색체가 순열일경우 사용
  • 한 부분집합을 고정함, 남은부분 부분집합 뒤부터 순서대로

간선 재조합

  • TSP를 위해 개발된 교차연산

  • 부모해의 특성을 보존, 변이가 적으면 교란이 너무 적음

  • 인접도시목록을 이용하여 TRACKING

  • 장단점?

    • 각각이 생각했던 최종 SOLUTION을 유지해나갈 수 있음

BFS를 이용한 유전자 재배치

  • 유전알고리즘 시작 전에 문제에 깃든 정보(유전자들 간의 관계)를 이용하여 유전자들의 위치를 재배치

변이 연산

  • 부모해에 없는 속성을 도입하여 탐색 공간을 넓히려는 목적을 가진 연산

전형적 변이

비균등 변이

수선

기타 변이 연산

세대형 유전 알고리즘

  • 해집단 내에서 염색체가 대부분(전체) 대치되므로 대치 연산이 비교전 간단

  • convergence(수렴)이 일어나기 어려움

  • 안정 상태 유전 알고리즘은 한 개 또는 소수의 해가 생기는 즉시 해집단 내의 해들과 대치하게 되므로 대치될 대상을 고르는 작업이 매우 중요한 영향을 미침
    -> 부분적인 최적화가 어렵다

GA가 유용한 문제들

  • 전통적 방법으로(결정론적인(deterministic)방법으로) 좋은 해를 잘 구하지 못하는 문제

GA가 소용 없는 문제들

  • 결정론적 알고리즘(deterministic algorithm)으로 쉽게 풀리는 문제

  • 결정론적 알고리즘(deterministic algorithm)으로 쉽게 풀리지 않으나 크기가 너무 작은 문제

    • 5-city TSP 등
  • Solution Space가 가늠할 수 없는 근사치 최대값을 찾기 유용한 알고리즘이다.

GA 장단점

장점

  • 빠르다 (메모리 사용량 적음) 엄청 큰 Search space에서.
  • 쉽다.

단점

  • Randomized - optimal하지 못하고 complete하지 못함
  • local maxima에 빠질 수 있음

Downhill Simplex Method

  • Starting Guess
  • N+1 각형을 유지

N+1개의 꼭짓점 갖는 구조
하나 이상의 테스트 포인트 유지

기본적인 Operation

  • 4개의 scalar parameters을 지정
    • reflection p
    • expansion w
    • contraction y
    • shrinkage a
      • Standard: p = 1, w = 2, y = 1/2 and a = 1/2

진행방식

  1. Order: 어떤 포인트가 가장 유명한지 판단
  2. Reflect
  3. Expand
  4. Contract
  • outside
  • inside

[강의정리] 알고리즘 Greedy Approach


Greedy Algorithm

  • Dynamic programming?
    • recursive property(재귀함수)로 풀 수 있는 문제를 DP로 풀 수 있음
  • Greedy approach
    • 결정을 해야 할 때마다 그 순간에 가장 좋다고 생각되는 것을 해답으로 선택
    • simple is best
    • local에서는 최적, 최적을 모아서 최종답을 만들어도 검증까지 해야함

Greedy Approach 설계 절차

  • Selection procedure (선정 과정)
    • 현재 상태에서 가장 좋다고 생각되는 해답을 찾음
  • Fesibility check(적정성 점검)
    • 적절한지 결정
  • Solution check(해답 점검)
    • 최적의 해인지 결정

Spanning Tree (신장 트리)

  • 그래프의 모든 vertex G를 가지고 있는 트리
  • 비방향성 그래프 G에서 순환 제거, 연결된 부분 그래프가 되도록 이음선 제거
  • G안에 있는 모든 정점을 다 포함하면서 트리가 되는 연결된 부분그래프

Minimum Spanning tree(최소비용 신장트리)

  • 가중치의 합이 최소가 되는 신장트리
  • 그래프는 트리형태(cycle없는)여야함

브루트포스 방식

  • 모든 신장트리를 다 고려해보고, 그중에서 최소비용을 고름

  • 분석:

    • 최악의경우, 지수보다 나쁨

Prim’s Algorithm

  • v1에서 vi까지 모든 정점을 돌면서 가장 가까이 있는 vnear찾음

    • nearest[i]: vi에서 가장 가까운 정점
    • distance[i]: 거리

Every-case Time Complexity Analysis

  • 단위연산: repeat 루프 안에 있는 두개의 for루프 안의 명령문

  • inputSize: 마디개수, n

  • 분석: repeat-루프가 n-1번 반복

    • T(n) = 2(n-1)(n-1)

최적여부 검증 (Optimality Proof)

  • Definition

    • 만약 E의 부분집합 F에 MST가 되도록 이음선을 추가할 수 있으면 (MST에 F가 포함되어있으면) F는 Promising(유망하다) 하다고 함
  • Lemma (*중요)

    • F는 E의 유망한 부분집합, Y는 F안에 있는 이음선 들에 의해서 연결된 정점의 집합.
    • 이때 Y에 있는 어떤 정점과 V-Y에 있는 어떤 정점을 잇는 이음선 중에서 가중치가 가장 작은 이음선을 e라고 하면..
    • F + e는 유망하다

Prim’s Algorithm 특징?

  • 특정 v1을 기준으로 뻗어나감

Kruskal’s Algorithm

  • edge그래프를 기준으로
  1. Edge List를 sorting해줌
  2. 순서대로 추가해도 되면 연결
  3. subset을 merge해줌
  4. 다연결될 때까지 반복

Worst-Cast Time Complexity Analysis

(시험출제)

  • 단위연산: 비교문
  • 입력크기: 정점의 수 n과 이음선의 수 m
  1. 정렬하는데 걸리는 시간 O(m lg m);
  2. n개의 서로소인 집합 set을 초기화 시간 O(n)
  3. 루프 m번 수행, 서로소인 집합 자료구조 사용, find, equal, merge등 포함하면 O(m lg n)
  • 여기서 m >= n-1, 1과 3은 2를 지배
    W(m, n) = O (m lg m);

  • 최악의 경우 모든 정점이 다른 모든 정점과 연결,
    M = n(n-1) / 2 = O(n^2), 최악의 경우 시간복잡도는 W(m, n) O(n^2 lg n)

Dijikstra’s Algorithm

  • 한 정점에서 다른 모든 정점으로 가는 최단경로 문제
  • Single-Source Shortest Paths: 시작점v1
  1. v1에서 갈수있는 경로로 table을 만듬
  2. table에서 가장 짧은 거리를 선택해서 그지역을 경유하는 경로까지 비교
  3. 모든 정점을 경유하는 거리를 비교함

Define touch & length

  • touch[i]: I까지 가는 경로의 마지막 노드
  • length[i]: 현재까지 구해진 최단거리

length[vnear] = -1로 만들어주는 이유?

  • 현재 선택된 노드를 다시 선택하는걸 방지

The Knapsack Problem

  • 배낭에 넣을 수 있는 최대 가치(Array)를 구하는 문제

The Knapsack Problem: Greedy

  • 탐욕적알고리즘: n개의 물건에 대해 모든 부분집합 고려
  • 부분집합의 수는 2^n개

The 0-1 Knapsack Problem

  • 일반 Fractional Knapsack problem: 남은공간 물건을 잘라서 꽉채울수있음

  • 0-1 Knapsack problem: 물건을 못자름

  • Fractional Knapsack: Greedy로 구할 수 있음(무게당 가치가 가장 높은순)

Dynamic Programming Approach

  • i > 0, w > 0 최대무게: w

  • i번째 항목중에서 얻어진 최고의 이익(optimal profit) = P[i][w];
    if w[i] <= w:
    max(P[i-1][w], p[i] + P[i-1][w-w[i]]);
    else:
    p[i-1][w];

여기서 P[i-1][w]는 i번째 항목을 포함시키지 않은 경우의 최고 이익,
p[i] + P[i-1][w-w[i]]는 i번째 항목을 포함시키는 경우 최고 이익

최대이익 P[n][W]는?

  • intP[0..n][0..W]의 2차원배열을 만든 후 각 항을 계산해서 넣음
  • P[0][w] = 0, P[i][0] = 0이므로 O(nW);

DP방법 보완

  • 임의로 W = n!이라 한다면 수행시간은 O(n*n!)이 되므로 무작정 알고리즘보다 나을게 없음

  • 최악을 O[n^2]로 만드는법? 무작위보다 빠르게하는법?

    • **P[n][W]를 계산하기 위해 (n-1)번째 행을 모두 계산할 필요 없음)

    P[n][W] = max(P[n-1][W], p[n] + P[n-1][W-w[n]]]);
    따라서 (n-1)번째 항은 P[n-1][W]와 P[n-1][W-w[n]]만 필요
    i번째항에 필요한 항목만 결정해서 계산함

  • Worst case

    • O(2^i)
  • O(min(2^n, nW));

Greedy vs. Dynamic Programming

Greedy DP
최적화문제 최적화문제
알고리즘이 존재하면 더 효율적 때론 불필요하게 복잡
단위출발점 최단경로 문제: O(N^2) 단위출발점 최단경로 문제: O(N^3)
알고리즘이 최적인지 증명해야함 최적화원칙이 적용되는지 점검만하면됨
0-1Knapsack은 못품 0-1Knapsack 풀수있음

[강의정리] 알고리즘 W6 (Dynamic Programming)


Dynamic programming

  • Similar to divide-and-conquer
  • small instances first, store the results, whenever we need a result, look it up instead of recomputing it.

알고리즘: Using Divide-and-Conquer

  • 문제: 이항계수를 계산한다
    • 입력: 음수가 아닌 정수 n과 k, 여기서 k <= n
    • 출력: bin, [n k]
1
2
3
4
5
6
int bin(int n, int k) {
if (k == 0 || n == k)
return 1;
else
return bin(n-1, k-1) + bin(n-1, k);
}

시간복잡도 분석:

  • 분할정복 알고리즘은 작성하기는 간단하지만, 효율적이지 않음
    • 이유? 재귀호출(recursive call)할때 같은 계산을 반복해서 수행하기 때문
    • 예를 들면, bin(n-1, k-1)과 bin(n-1, k)는 둘다 bin(n-2, k-1)의 결과가 필요한데, 따로 중복 계산이 됨

[n: k]를 구하기 위해서 이 알고리즘이 계산하는 항(term)의 개수는 2[n: k]-1이다. (증명을 해보자)

증명: (n에 대한 수학적 귀납법으로 증명)

  • 귀납출발점: 항의 개수 n이 1일 때 2[n: k]-1 = 2 x 1 - 1 = 1이 됨을 보이면 된다.
           [1: k]는 k=0이나 1일때 1이므로 항의 개수는 항상 1이다.
    
  • 귀납가정: [n: k]를 계산하기 위한 항의 개수는 2[n: k] - 1이라고 가정한다.
  • 귀납절차: [n+1: k]를 계산하기 위한 항의 개수가 2[n+1: k] - 1임을 보이면 된다.
         알고리즘에 의해서 [n+1: k] = [n: k-1] + [n: k] 이므로, [n+1: k]를 계산하기 위한 항의 총 개수는 [n: k-1]을 계산하기 위한 총 개수와 [n: k]를 계산하기 위한 항의 총 개수에다가 이 둘을 더하기 위한 항 1을 더한 수가 된다.
         그런데 [n: k-1]을 계산하기 위한 항의 개수는 가정에 의해서 2[n: k-1] -1이고, [n: k]를 계산하기 위한 항의 개수는 가정에 의해서 2[n: k] - 1이다.
    

동적계획식 알고리즘 설계전략

  1. Establish a recursive property (재귀 관계식을 정립):
  • 2차원 배열 B를 만들고, 각 B[i][j]에는 [i: j]값을 저장하도록 하면, 그 값은 다음과 같은 관계식으로 계산할 수 있다.
  1. Solve an instance of the problem in a bottom-up fashion:
    • [n: k]를 구하기 위해서는 다음과 같이 B[0][0]부터 시작하여 위에서 아래로 재귀 관계식을 적용하여 배열을 채워 나가면 된다.
      결국 값은 B[n][k]에 저장된다.
  • 문제: 이항계수를 계산한다.
    • 입력: 음수가 아닌 정수 n 과 k, 여기서 k <= n
    • 출력: bin, [n: k]
1
2
3
4
5
6
7
8
9
int bin2(int n, int k) {
index i, j;
int B[0..n][0..k];
for(i = 0; i <= n; i++)
for(j = 0; j <= minimum(i,k); j++)
if(j==0 || j==1) B[i][j] = 1;
else B[i][j] = B[i-1][j-1] + B[i-1][j];
return B[n][k];
}

동적계획 알고리즘의 분석

  • 단위연산: for-j 루프 안의 문장

  • 입력의 크기: n, k
    i = 0일 때 j-루프 수행 횟수 : 1
    i = 1일 때 j-루프 수행 횟수 : 2
    i = 2일 때 j-루프 수행 횟수 : 3
    ……………
    i = k-1일 때 j-루프 수행 횟수 : k
    i = k일 때 j-루프 수행 횟수 : k + 1
    i = k+1일 때 j-루프 수행 횟수 : k + 1
    ……………
    i = n일 때 j-루프 수행 횟수 : k + 1

    따라서 총 수행횟수는:
    1 + 2 + 3 + … + k + (k+1) + … + (k+1) = k(k+1)/2 + (n-k+1)(k+1) = (2n-k+2)(k+1)/2 = O(nk)

그래프

그래프 용어

  • 정점(vertex, node), 이음선(edge, arc)
  • 방향 그래프(directed graph, or digraph)
  • 가중치(weight), 가중치 포함 그래프 (weighted graph)
  • 경로(path) - 두 정점사이에 edge가 있는 정점들의 나열
  • 단순경로(simple path) - 같은 정점을 두 번 지나지 않음
  • 순환(cycle) - 한 정점에서 다시 그 정점으로 돌아오는 경로
  • 순환그래프(cyclic graph) vs 비순환 그래프 (acyclic graph)
  • 길이(length): the sum of weights on the path (weighted graph)
              the number of edges on the path (unweighted graph)
    

Shortest Path

  • Shortest Path: 한 도시에서 다른 도시로 직항로가 없는 경우

               가장 빨리 갈 수 있는 항로를 찾는 문제
    
  • 문제: 가중치 포함, 방향성 그래프에서 최단경로 찾기

  • Optimization problem (최적화 문제)의 정의

    • 주어진 문제에 대하여 하나 이상의 많은 해답 후보가 존재할 때, 이와 연관된 값이 최소 또는 최대인 해답(optimal solution)을 찾아야 하는 문제
    • 에너지 최소화 문제라고도 함.
  • shortest Path는 Optimization problem에 속함

Brute-force algorithm(무작정 알고리즘)

  • 한 정점에서 다른 정점으로의 모든 경로의 길이를 구한 뒤, 그들 중에서 최소길이를 찾는다.

동적계획식 설계전략 - 자료구조

  • 그래프의 인접행렬(adjacent matrix)식 표현: W

동적계획식 설계절차

  1. Establish a recursive property

    • D(k-1)을 가지고 D(k)를 계산할 수 있는 재귀 관계식을 정립
      • D(k)[i][j] = minimum(D(k-1)[i][j], D(k-1)[i][k] + D(k-1)[k][j])
    • 경우 1: {v1, v2,…, vk}의 정점들 만을 통해서 vi에서 vj로 가는 최단 경로가 vk를 거치지 않는 경우,
          보기: D(5)[1][3] = D(4)[1][3] = 3
      
    • 경우 2: {v1, v2,…, vk}의 정점들 만을 통해서 vi에서 vj로 가는 최단 경로가 vk를 거치는 경우,
          보기: D(2)[5][3] = D(1)[5][2] + D(1)[2][3] = 4 + 3 = 7
          보기: D(2)[5][4]
      
  2. 상향식으로 k=1부터 n까지 다음과 같이 이 과정을 반복하여 해를 구한다.
    D(0), D(1),……,D(n)

Floyd’s Algorithm I

  • 가중치 포함 그래프의 각 정점에서 다른 모든 정점까지의 최단거리를 계산
1
2
3
4
5
6
7
8
void floyd(int n, const number W[][], number D[][]) {
int i, j, k;
D = W;
for(k=1; k <= n; k++)
for(i=1; i <= n; i++)
for(j=1; j <= n; j++)
D[i][j] = minimum(D[i][j], D[i][k]+D[k][j]);
}

Floyd’s Algorithm II

  • 가중치 포함 그래프의 각 정점에서 다른 모든 정점까지의 최단거리를 계산, 각각의 최단경로를 구하라.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void floyd2(int n, const number W[][], number D[][], index P[][]) {
index i, j, k;
for(i=1; i <= n; i++)
for(j=1; j <= n; j++)
P[i][j] = 0;
D = W;
for(k=1; k <= n; k++)
for(i=1; i <= n; i++)
for(j=1; j <= n; j++)
if(D[i][k] + D[k][j] < D[i][j]) {
P[i][j] = k;
D[i][j] = D[i][k] + D[k][j];
}
}

최단경로의 출력

1
2
3
4
5
6
7
void path(index q,r) {
if(P[q][r] != 0) {
path(q, P[q][r]);
count << "v" << P[q][r];
path(P[q][r], r);
}
}

최적의 원칙

  • 어떤문제의 입력에 대한 최적해가 그 입력을 나누어 쪼갠 여러 부분에 대한 최적 해를 항상 포함하고 있으면 그 문제는 최적의 원칙(the principle of optimality)이 적용된다 라고 한다.

Optimal Binary Search Trees

  • definition
    • binary search tree
      • Ordered set
      • Each node contain one key
      • The keys in the left subtree are less than or equal to the key in that tree
    • Depth - number of edges from the root
    • balanced - if the depth of the 2 subtrees of every node never different by more than 1
    • optimal - the average time it takes to locate a key is minimized
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void optsearchtree(int n, const float p[], float& minavg, index R[][]) {
index i, j, k, diagonal;
float A[1...n+1][0..n];
for(i=1; i<=n; i++) {
A[i][i-1] = 0; A[i][i] = p[i]; R[i][i] = i; R[i][i-1] = 0;
A[n+1][n] = 0; R[n+1][n] = 0;
for(diagonal=1; diagonal <= n-1; diagonal++)
for(i=1; i<=n-diagonal; i++) {
j = i + diagonal;
A[i][j] = minimum(A[i][k-1] + A[k+1][j]) +
R[i][j] = a value of k that gave the minimum;
}
minavg = A[1][n];
}
}

The Traveling Salesperson Problem

  • Problem Definition

    • Determine a shortest route that starts at the salesperson’s home city, visits each of the cities once, and ends up at the home city
  • Adjacent matrix W

    • V = set of all the vertices
    • A = a subset of V
    • D[vi][A] = length of a shortest path from vi to v1
              passing through each vertex in A exactly once
      
  • Length of an optimal tour = minimum(W[1][j] + D[vj][V - {v1, vj}])

```C
void travel(int n, const number W[][], index P[][], number& minlength) {
index i, j, k;
number D[1..n][subset of V-{v1}];
for(i=2; i<=n; i++)
D[i][0] = W[i][1];

for(k=1; k<=n-2; k++)
for(all subsets A V-{v1} containing k vertices)
for(i such that i!= 1 and vi is not in A) {
D[i][A] = min(j:vj A)(W[i][j]+D[j][A-{vj}]);
P[i][A] = value of j that gave the minimum;
}
D[1][V-{v1}] = min(2<=j<=n)(W[1][j] + D[j][A-{v1,vj}]);
P[1][V-{v1}] = value of j that gave the minimum;
minlength = D[1][V-{v1}]
}

[강의정리] 알고리즘 W5 (quicksort, sorting algo)


Quicksort

  • 분할교환정렬(patition exchange sort)라고 불린다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    void quicksort(index low, index high) {
    index pivotpoint;
    if (high > low) {
    partition(low, high, pivotpoint);
    quicksort(low, pivotpoint-1);
    quicksort(pivotpoint+1, high);
    }
    }

    void partition(index low, index high, index& pivotpoint) {
    index i, j;
    keytype pivotitem;
    pivotitem = S[low]; //pivotitem을 위한 첫번째 항목을 고른다.
    j = low;
    for(i = low + 1; i <= high; i++)
    if(S[i] < pivotitem) {
    j++;
    exchange S[i] and S[j];
    }
    pivotpoint = j;
    exchange S[low] and S[pivotpoint]; //pivotitem값을 pivotpoint에 넣는다
    }

분석

  • 단위연산: S[i]와 key와의 비교
  • 입력크기: 부분배열이 가지고 있는 항목의 수, n = high - low + 1
  • 분석: 배열의 첫번째 항목만 제외하고 모든 항목을 한번씩 비교하므로, T(n) = n - 1이다.

최악의 경우 시간복잡도 분석

  • 단위연산: 분할 알고리즘의 S[i]와 pivotitem과의 비교
  • 입력크기: 배열 S가 가지고 있는 항목의 수, n
  • 분석: 이미 비내림차순으로 정렬이 되어있는 배열을 정렬하려는 경우가 최악의 경우가 됨.
      비내림차순이면 첫번째(pivot)항목보다 작은 항목은 없으므로, 크기가 n인 배열은 크기가 0인 부분은 왼쪽에 오고, 크기가 n-1인 부분배열은 오른쪽에 오도록 하여 계속 쪼개진다. 따라서,
      T(n) = T(0) + T(n-1) - n - 1
      그런데 T(0) = 0이므로 재현식은 다음과 같이 된다.
      T(n) = T(n-1) + n - 1, n > 0이면
      T(0) = 0 
      
      이 재현식을 풀면,
      T(n) = T(n-1) + n - 1
      T(n-1) = T(n-2) + n - 2
      T(n-2) = T(n-3) + n - 3
      ...
      T(2) = T(1) + 1
      T(1) = T(0) + 0
      T(0) = 0
      
      T(n) = 1 + 2 + ... + (n-1) = n(n-1) / 2
    

평균의 경우를 고려한 시간복잡도 분석

  • 단위연산: 분할알고리즘의 S[i]와 pivotitem과의 비교
  • 입력크기: 배열이 S가 가지고 있는 항목의 수, n
  • 분석:

[강의정리] 알고리즘 week4 (merge sort)


Divide-and-Conquer

  • 분할정복식 설계전략
  • 분할(Divide): 해결하기 쉽도록 문제를 여러 개의 작은 부분으로 나눔
  • 정복(Conquer): 나눈 작은 문제를 각각 해결
  • 통합(Convbine): 해결된 해답을 모음
  • 이러한방식을 Top-Down(하향식) 접근 방법이라고 한다

Binary Search(이분검색): 재귀 알고리즘

  • 분할: 배열을 반으로 나누어서 x가 중앙에 위치한 항목보다 작으면 왼쪽에 위치한 배열 반쪽을 선택, 그렇지 않으면 오른쪽에 위치한 배열 반쪽을 선택
  • 정복: 선택된 반쪽 배열에서 X를 찾는다
  • 통합: 필요없음

재귀 알고리즘(recursive algorithm)에서 모든 재귀호출이 알고리즘의 마지막(꼬리) 부분에서 이루어 질 때 꼬리 재귀호출(tail recursion)이라고 함 - 그 알고리즘은 반복 알고리즘(iterative algorithm)으로 변환하기 수월ㅋ

최악의 경우 시간복잡도 분석

  • 단위연산: x와 S[mid]의 비교
  • 입력 크기: 배열의 크기 n(= high - low + 1)
  • 알고리즘에서는 단위연산으로 설정한 조건문을 while루프 내에서 2번 수행하지만, 사실상 비교는 한번만 수행
    (1) 어셈블리언어로는 하나의 조건 명령으로 충분히 구현 가능
    (2) x를 찾기 전까지는 항상 2개의 조건문을 수행하므로 하나로 묶어서 한 단위로 취급해도 됨

경우 1: 검색하게 될 반쪽 배열의 크기가 항상 정확하게 n/2이 되는 경우

  • 시간복잡도를 나타내주는 재현식(recurrence)는 다음과 같다
    W(n) = W(n/2)+1, n > 1이고, n = 2k(k>=1)
    W(1) = 1
    이식의 해는 다음과 같이 구할 수 있다
    W(1) = 1
    W(2) = W(1) + 1 = 2
    W(4) = w(2) + 1 = 3
    W(8) = W(4) + 1 = 4
    W(16) = W(8) + 1 = 5

    W(2k)=k+1

    W(n) = lg n + 1

    증명: 수학접 귀납법:

    귀납 출발점: n=1이면, W(1) = 1 = lg 1 + 1.
    귀납 가정: 2의 거듭제곱(power)인 양의 정수 n에 대해서, W(n)=lg n + 1라고 가정
    귀납 단계: W(2n) = lg(2n) + 1임을 보이면 된다. 재현식을 사용하면,
    W(2n) = W(n) + 1

      = lg n + 1 + 1
      = lg n + lg 2 + 1
      = lg(2n) + 1
    

경우 2: 일반적인 경우 - 반쪽 배열의 크기는 [n/2]이 됨

합병정렬(Mergesort)

1
2
3
4
5
6
7
8
9
10
11
12
void mergesort (int n, keytype S[]) {
const int h = n / 2, m = n - h;
keytype U[1..h], V[1..m];

if(n>1) {
copy S[1] through S[h] to U[1] through U[h];
copy S[h+1] through S[n] to V[1] through V[m];
mergesort(h,U);
mergesort(m,V);
merge(h,m,U,V,S);
}
}

시간복잡도 분석

합병 알고리즘의 최악의 경우 시간복잡도 분석

  • 단위연산: U[i]와 V[j]의 비교
  • 입력크기: 2개의 입력 배열에 각각 들어있는 항목의 개수: h와 m
  • 분석: i=h이고, j=m-1인 상태로 루프(loop)에서 빠져 나가는 때가 최악의 경우로서 (V에 있는 처음 m-1개의 항목이 S의 앞부분에 위치하고, U에 있는 h개의 모든 항목이 그 뒤에 위치하는 경우), 이때 단위연산의 실행 횟수는 h + m - 1이다. 따라서 최악의 경우 합병하는 시간복잡도는 W(h, m) = h + m - 1.

합병정렬 알고리즘의 최악의 경우 시간복잡도 분석

  • 단위연산: 합병 알고리즘 merge에서 발생하는 비교
  • 입력크기: 배열 S에 들어 있는 항목의 개수 n
  • 분석: 최악의 경우 수행시간은 W(h,m) = W(h) + W(m) + h + m - 1이 된다. 여기서 W(h)는 U를 정렬하는데 걸리는 시간, W(m)은 V를 정렬하는데 걸리는 시간, 그리고 h + m - 1은 합병하는데 걸리는 시간이다. 정수 n을 2k(k>=1)이라고 가정하면, h= n/2, m=n/2가 된다. 따라서 최악의 경우 재현식은:
    W(n) = 2W(n/2)+n-1 n>1이고, n=2k(k>=1)
    W(1) = 0 왜냐하면 합병이 전혀 이루어지지 않으므로 이 재현식의 해는 아래의 도사정리의 2번을 적용하면
    W(n) = O(n lg n)이 된다.

[강의정리] 알고리즘 W3 - Data Structures


Data Structure

List

Linked List

  • 배열과 달리 크기를 바꿀 수 있는 자료구조

  • 각 노드는 다음노드를 가르키는 포인터를 가짐

  • 첫번째노드: 헤드(Head), 마지막 노드: 테일(Tail)

Double Linked List

  • 각 노드는 다음노드와 이전노드를 가르키는 포인터를 가짐

Circle Linked List

  • Head가 Tail을 물고있는 형태의 Linked List

Stack

  • 먼저 들어간 요소가 나중에 나옴 (First-In, Last-Out: LIFO)

Queue

  • 먼저 들어간 요소가 먼저 나옴 (First-In, First-Out: FIFO)

Circle Queue

Linked Queue

Tree

  • 나무를 닮은 구조
  • Root, Branch, Leaf로 이루어져 있음

    깊이(Depth): 루트노드에서 해당 노드까지의 경로의 길이

    레벨(Level): 같은 깊이를 가지는 노드의 집합

    높이(Height): “가장 깊은 곳”에 있는 잎노드까지의 깊이

차수(Degree): 자식 노드의 개수

트리의 차수: 트리 내에 있는 노드들 가운데 자식 노드가 가장 많은 노드의 차수

이진트리(Binary Tree)

  • 모든 노드가 최대 “2 개”의 자식을 가질 수 있는 트리

    포화 이진 트리(Full Binary Tree)

  • 모든 노드가 대대손손이 자식을 둘씩 가지고 있는 이진 트리

    완전 이진 트리

  • 잎 노드들이 트리의 왼쪽부터 차곡차곡 채워진 트리

    완전 높이 균형 트리(Completely Height Balanced Tree)

  • 루트 노드를 기준으로 왼ㅉ고 하위 트리와 오른ㅉ고 하위 트리의 높이가 같은 이진트리

Priority Queue

  • 우선순위 속성을 갖는 데이터를 다룸

Heap

  • 힙 순서 속성(Heap Order Property)를 만족하는 완전 이진 트리
  • 힙 순서 속성 : 트리 내의 모든 노드가 부모 노드보다 커야 한다는 규칙

Graph

인접 행렬 : 정점 끼리의 인접 관계를 나타내는 행렬

[강의정리] 알고리즘 W2


Introduction to Algorithm

알고리즘의 학습목표

Design(설계)

알고리즘 설계하는 기법

Analysis(분석)

  • 알고리즘을 분석, 시간/공간 복잡도 구하기

Computational Complexity(계산복잡도)

  • 문제를 분석하여 계산적 복잡도 구하기

알고리즘의 분석

시간복잡도(Time Complexity) 분석

  • 입력 크기에 따라서 단위연산이 몇번 수행되는지 결정하는 절차(n)

표현 척도

입력크기(input size)

  • 배열의 크기, 리스트의 길이, 행렬에서 행과 열의 크기, 트리에서 마디와 이음선의 수, 그래프에서는 정점과 간선의 수

    단위연산(basic operation)

  • 비교(comparison), 지정(assignment) 등 시간복잡도에 가장 크게 영향을 미치는 연산

분석 방법의 종류

  • 모든경우 분석(Every-case analysis)
  • 최악의 경우 분석(Worst-case analysis)
  • 평균의 경우 분석(Average-case analysis)
  • 최선의 경우 분석(Best-case analysis)

계산복잡도

Big O 표기법

정의 : 점근적 상한(Asymptotic Upper Bound)

차수의 주요 성질

복잡도 함수 순서

  • lgn, n, nlgn, n2, nj, nk, an, bnn, n!
    k > j > 2, b > a > 1