분할 정복 (Divide-and-Conquer)

Slides:



Advertisements
Similar presentations
알고리즘 개론 :15 시작 장준영 1. 상/중/하상/중/하 상 – 나는 알고리즘을 매우 잘 알고, 좀 더 어려운 난 이도의 문제들을 보고 싶다. 중 – 어느정도 알고리즘을 구현해본 적이 있다. 하 – 알고리즘의 A 조차 모른다. 2.
Advertisements

알고리즘 기본 개념 정렬 알고리즘 탐색 알고리즘 알고리즘 복잡도.
(Program = Algorithm + Data Structure)
Report #5 - due: 4/13 다음 10*5의 희소 행렬 A, B를 고려하라.
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
알고리즘(Algorithm)  알고리즘 개요 (효율, 분석, 차수) Part 1 강원대학교 컴퓨터과학전공 문양세.
보고서 #7 (기한: 6/2) 2개의 스택, stk1, stk2를 이용하여 큐를 구현하라.
알고리즘 강의 슬라이드 2 분할정복 강의 슬라이드 #2
7. 계산복잡도 개론 정렬 문제 알고리즘 강의 슬라이드 7 정렬문제
자료구조론 11장 정렬(sort).
CHAP 2:순환 순천향대학교 컴퓨터공학과.
Chapter 02 순환 (Recursion).
빠른정렬(Quick Sort) – 개요 (1/2)
CHAP 2:순환 C로 쉽게 풀어쓴 자료구조 생능출판사 2005.
8장 함수 함수의 필요성 라이브러리 함수와 사용자 정의 함수 함수의 정의, 원형, 호출 배열을 함수 인자로 전달 재귀호출.
컴퓨터 프로그래밍 기초 #02 : printf(), scanf()
보고서 #5(제출기한: 10/14) 다음 문제를 해결하시오.
CHAP 9: 정렬 (part 2) 순천향대학교 컴퓨터학부 하 상 호.
CHAP 9:정렬 C로 쉽게 풀어쓴 자료구조 Slide 1 (of 44).
프로그래밍 개요
어서와 C언어는 처음이지 제14장.
CHAP 9: 정렬 순천향대학교 컴퓨터학부 하 상 호.
Lesson 4. 수식과 연산자.
자료구조: CHAP 7 트리 –review 순천향대학교 컴퓨터공학과 하 상 호.
Ch.03 Dynamic Programming (동적 프로그래밍 or 동적 계획법)
CHAP 2:순환.
Quiz #7 다음 수들을 합병 정렬과 퀵 정렬 알고리즘을 이용하여 오름 차순으로 정렬하였을 때, 데이터 이동 회수를 각각 구하라. 여러분은 정렬 과정을 단계별로 보이면서 이동 회수를 추적해야 한다. 단, 퀵 정렬시에 피봇으로 배열의 왼쪽 첫 번째 원소를 선택한다. 5.
제 1 장 알고리즘 : 효율, 분석, 그리고 차수.
Ch.02 Divide and Conquer (분할정복)
Term Projects 다음에 주어진 2개중에서 한 개를 선택하여 문제를 해결하시오. 기한: 중간 보고서: 5/30 (5)
알고리즘(Algorithm)  알고리즘 개요 (효율, 분석, 차수) Part 년 봄학기
[CPA340] Algorithms and Practice Youn-Hee Han
[CPA340] Algorithms and Practice Youn-Hee Han
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
CHAP 2:순환 C로 쉽게 풀어쓴 자료구조 생능출판사 Slide 1 (of 19).
제 1 강.
행렬의 개요 행렬은 수를 원소로 지니는 다차원 배열이다. mn (“m by n”) 행렬은 m개의 행과 n개의 열을 갖는다.
행렬의 개요 행렬은 수를 원소로 지니는 다차원 배열이다. mn (“m by n”) 행렬은 m개의 행과 n개의 열을 갖는다.
알고리즘 강의 슬라이드 2 분할정복 분할정복법 도경구역, 알고리즘, 사이텍미디어, 1999.
 Divide and Conquer (분할정복)
컴퓨터 프로그래밍 기초 - 5th : 조건문(if, else if, else, switch-case) -
Hanoi Tower.
김선균 컴퓨터 프로그래밍 기초 - 7th : 함수 - 김선균
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
 Divide and Conquer (분할정복)
1. 2진 시스템.
보고서 #7 (기한: 6/2) 2개의 스택, stk1, stk2를 이용하여 큐를 구현하라.
 Divide and Conquer (분할정복)
동적계획법과 최적화 문제 Dynamic Programming을 사용한 최적화 문제를 해결하는 알고리즘 설계 절차
CHAP 12: 탐색 순천향대학교 컴퓨터학부 하 상 호.
[CPA340] Algorithms and Practice Youn-Hee Han
CHAP 2:순환 C로 쉽게 풀어쓴 자료구조 생능출판사 2005.
알고리즘의 분석(analysis) 공간적 효율성(Space Efficiency)과 시간적 효율성(Time Efficiency)
합병정렬(Merge Sort) (1/2) 문제: n개의 정수를 (비내림차순으로) 정렬하시오.
2nd day Indexing and Slicing
1학기 수학 연산 풀이 (3학년) 와이즈캠프 담임선생님.
DA :: 퀵 정렬 Quick Sort 퀵 정렬은 비교방식의 정렬 중 가장 빠른 정렬방법이다.
5장. 선택 알고리즘.
빠른정렬(Quick Sort) – 개요 (1/2)
알고리즘 강의 슬라이드 2 분할정복 제 2 장 분할정복 도경구역, 알고리즘, 사이텍미디어, 1999.
CHAP 2:순환.
Homework #8 (실습 #7) [1/2] 다음을 수행하는 PHP 프로그램을 작성하여 프로그램과 결과물을 프린트하여 제출한다. sin(45º), cos(45º), tan(45º)를 출력하는 프로그램을 작성하시오. 피보나치 수를 구하는 함수 fib($n)을 작성하고,
쉽게 배우는 알고리즘 2장. 점화식과 점근적 복잡도 분석
알고리즘의 분석(analysis) 공간적 효율성(Space Efficiency)과 시간적 효율성(Time Efficiency)
알고리즘(Algorithm) – Divide and Conquer (분할정복)
제 4 장 Record.
빠른정렬(Quick Sort) – 개요 (1/2)
C++ Espresso 제15장 STL 알고리즘.
알고리즘의 분석(analysis) 공간적 효율성(Space Efficiency)과 시간적 효율성(Time Efficiency)
Presentation transcript:

분할 정복 (Divide-and-Conquer)

분할정복식 설계 분할(Divide) 정복(Conquer) 통합(Combine) 하향식(top-down) 해결하기 쉽도록 문제를 여러 개의 작은 부분으로 나눈다. 정복(Conquer) 나눈 작은 문제를 각각 해결한다. 통합(Combine) (필요하다면) 해결된 해답을 모은다. 하향식(top-down) 이분 검색 피보나찌

이분 검색(재귀적 방법) 문제 입력 출력 설계전략 크기가 n인 정렬된 배열 S에 x가 있는지를 결정하라. 자연수 n, 비내림차순으로 정렬된 배열 S[1..n], 찾고자 하는 항목 x 출력 locationout - x가 S의 어디에 있는지의 위치. 만약 x가 S에 없다면 0 설계전략 x가 배열의 중간에 위치하고 있는 항목과 같으면, “빙고”, 찾았다! 그렇지 않으면: 분할: 배열을 반으로 나누어서 x가 중앙에 위치한 항목보다 작으면 왼쪽에 위치한 배열 반쪽을 선택하고, 그렇지 않으면 오른쪽에 위치한 배열 반쪽을 선택한다. 정복: 선택된 반쪽 배열에서 x를 찾는다. 통합: (필요 없음)

의사 코드 index location (index low, index high) { index mid; if (low > high) return 0; // 찾지 못했음 else { mid = (low + high) / 2 // 정수 나눗셈 (나머지 버림) if (x == S[mid]) return mid; // 찾았음 else if (x < S[mid]) return location(low, mid-1); // 왼쪽 반을 선택함 else return location(mid+1, high); // 오른쪽 반을 선택함 } … locationout = location(1, n);

토의 입력: n,x,S 재귀 형식 파라미터? 꼬리 재귀(tail-recursion) 반복 알고리즘과 비교 void binsearch(…) { index low, high, mid; low = 1; high = n; location = 0; while (low <= high && location == 0) { mid = (low + high) / 2; if (x == S[mid]) location = mid; else if (x < S[mid]) high = mid - 1; else low = mid + 1; }

재귀 vs. 반복 반복형이 재귀형보다 빠르다. 재귀 반복 재귀형는 함수 호출이 재귀적으로 이루어지지만 반복형은 이를 피할 수 있다. 하지만, 계산 복잡도상의 큰 이득은 없다. 재귀 반복

이분검색 – 최악의 경우 분석 단위연산: x와 S[mid]의 비교 몇 번? 입력 크기: 배열의 크기 n (= high - low + 1)

최악의 경우 경우 1: 반쪽 배열의 크기가 정확하게 n/2이 될 때 최악의 경우 재현식(recurrence equation)

최악의 경우 경우 2: n이 2의 거듭제곱으로 제한되지 않았을 때 (과제)증명: 수학적 귀납법 이용

합병정렬(Mergesort) 분할 정복법 절차 쌍방 합병(two-way merging): 같은 순으로 정렬되어 있는 두 개의 배열을 정렬된 하나의 배열로 만드는 과정 합병을 반복적으로 적용하여 배열을 정렬 절차 분할: 배열을 n/2개의 요소로 구성된 2개의 부분배열로 분할 정복: 부분배열 정렬 통합: 정렬된 각 부분배열을 하나의 정렬된 배열로 합병

합병정렬 문제: n개의 정수를 비내림차순으로 정렬하시오. 입력: 정수 n, 크기가 n인 배열 S[1..n] 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); }

합병(Merge) 문제: 두 개의 정렬된 배열을 하나의 정렬된 배열로 합병 merge(h,m,U,V,S); 문제: 두 개의 정렬된 배열을 하나의 정렬된 배열로 합병 입력: (1) 양의 정수 h, m (2) 정렬된 배열 U[1..h], V[1..m] 출력: U와 V에 있는 키들을 하나의 배열에 정렬한 S[1..h+m] void merge(h, m, U[], V[], S[]) { index i, j, k; i = 1; j = 1; k = 1; while (i <= h && j <= m) { if (U[i] < V[j]) { S[k] = U[i]; i++;} else { S[k] = V[j]; j++;} k++; } if (i > h) copy V[j] through V[m] to S[k] through S[h+m]; else copy U[i] through U[h] to S[k] through S[h+m]; 표 2.1

합병 알고리즘: 최악의 경우 시간복잡도 분석 단위연산: U[i]와 V[j]의 비교 입력크기: h + m 분석: 최악의 경우 merge(h,m,U,V,S); 합병 알고리즘: 최악의 경우 시간복잡도 분석 단위연산: U[i]와 V[j]의 비교 입력크기: h + m 분석: 최악의 경우

합병정렬 알고리즘: 최악의 경우 시간복잡도 분석 mergesort (int n, keytype S[]) 합병정렬 알고리즘: 최악의 경우 시간복잡도 분석 단위 연산: merge에서 일어나는 비교 연산 입력 크기: n 배열 S의 크기 분석: 과제:

합병정렬 알고리즘: 최악의 경우 시간복잡도 분석 mergesort (int n, keytype S[]) 합병정렬 알고리즘: 최악의 경우 시간복잡도 분석 단위 연산: merge에서 일어나는 비교 연산 입력 크기: n 배열 S의 크기 분석:

토의 공간 복잡도 얼마만큼의 저장장소가 필요할까? Cf) 제자리 정렬(in-place sort) 알고리즘 공간 복잡도 향상을 위한 알고리즘

공간 복잡도가 향상된 알고리즘 void mergesort2 (index low, index high) { index mid; if (low < high) { mid = (low + high) / 2; mergesort2(low, mid); mergesort2(mid+1, high); merge2(low, mid, high); }

merge2(low, mid, high); 문제: 두 개의 정렬된 배열을 하나의 정렬된 배열로 합병하시오. 입력: (1) 첨자 low, mid, high, (2) 부분 배열 S[low..high], 여기서 S[low..mid]와 S[mid+1..high]는 이미 각각 정렬이 완료되어 있음. 출력: 정렬이 완료된 부분배열 S[low..high]

merge2(low, mid, high); void merge2(index low, index mid, index high) { index i, j, k; U[low..high]; i = low; j = mid + 1; k = low; while (i <= mid && j <= high) { if (S[i] < S[j]) { U[k] = S[i]; i++; } else { U[k] = S[j]; j++; } k++; } if (i > mid) move S[j] through S[high] to U[k] through U[high]; else move S[i] through S[mid] to U[k] through U[high]; move U[low] through U[high] to S[low] through S[high]; }

빠른정렬(Quicksort) 1962년 호아 정말로 빠른 정렬 일까? 분할교환정렬(Partition exchange sort)

빠른정렬 알고리즘 void quicksort (index low, index high) { index pivotpoint; if (high > low) { partition(low, high, pivotpoint); quicksort(low, pivotpoint-1); quicksort(pivotpoint+1, high); }

분할 알고리즘: partition(low, high, pivotpoint); 문제: 빠른정렬을 위해 배열 S를 분할하라. 입력: 색인 low와 high,부분배열 S[low..high] 출력: 부분배열 S의 pivotPoint 색인 void partition (index low, index high, index& pivotpoint) { index i, j; keytype pivotitem; pivotitem = S[low]; //choose first item for 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]; //put pivotitem at pivotpoint

분할 알고리즘 분석 모든 경우를 고려한 시간복잡도 분석 단위연산: S[i] < pivotitem 입력크기: n = high - low + 1 분석: T(n) = n - 1

빠른 정렬 알고리즘 분석 최악의 경우 가장 최악은? 정렬되어 있는 경우

빠른 정렬 알고리즘 최악의 경우 증명 모든 정수 n에 대해서, 임을 증명하시오. 증명:(수학적 귀납법) 귀납 출발점: 귀납 가정: 귀납 단계: 과제: why?

빠른 정렬 알고리즘 평균의 경우 분석

행렬 곱셈(Matrix Multiplication) 문제: nxn 행렬 곱 입력: 양수 n, nxn 크기의 행렬 A,B 출력: C = AB 알고리즘 void matrixmult (int n, const number A[][], const number B[][],number C[][]) { index i, j, k; for (i = 1; i <= n; i++) for (j = 1; j <= n; j++) { C[i][j] = 0; for (k = 1; k <= n; k++) C[i][j] = C[i][j] + A[i][k] * B[k][j]; }

Strassen의 행렬 곱셈 알고리즘(2x2) 단순방법: 곱셈 ? 덧셈 ? Strassen: 곱셈 ? 덧셈 ?

nxn 일때 n이 2의 거듭제곱일 때,

Strassen의 행렬 곱셈 알고리즘 void strassen (int n, n*n_matrix A, n*n_matrix B, n*n_matrix& C) { if (n <= threshold) 단순한 알고리즘을 사용하여 C = A * B를 계산; else { A를 4개의 부분행렬 A11, A12, A21, A22로 분할; B를 4개의 부분행렬 B11, B12, B21, B22로 분할; 쉬트라쎈의 방법을 사용하여 C = A * B를 계산; // 재귀 호출의 예: strassen(n/2, A11+A12, B11+B22,M1) }

시간 복잡도 분석 단위연산: 곱셈 입력크기: n 임계값: 1

시간 복잡도 분석 단위연산: 덧셈/뺄셈 입력크기: n 임계값: 1

토의 n이 2의 거듭제곱이 아니면? 얼마나 빨라졌는가?

분할정복을 피해야 하는 경우 크기가 n인 입력이 2개 이상의 조각으로 분할되며, 분할된 부분들의 크기가 거의 n에 가깝게되는 경우 ⇒시간복잡도: 지수(exponential) 시간 크기가 n인 입력이 거의 n개의 조각으로 분할되며, 분할된 부분의 크기가 n/c인 경우. 여기서c는 상수이다. ⇒ 시간복잡도: