Chapter 1 Basic Concepts

Slides:



Advertisements
Similar presentations
컴퓨터와 인터넷.
Advertisements

10. 예외 처리.
ㅎㅎ 구조체 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스 구조체 배열.
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
(Program = Algorithm + Data Structure)
2장. 프로그램의 기본 구성. 2장. 프로그램의 기본 구성 2-1"Hello, World!" 들여다 보기 /* Hello.c */ #include int main(void) { printf("Hello, World! \n"); return 0;
최윤정 Java 프로그래밍 클래스 상속 최윤정
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
시스템 생명 주기(System Life Cycle)(1/2)
제 9 장 구조체와 공용체.
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
시스템 생명 주기(System Life Cycle)(1/2)
컴퓨터 프로그래밍 기초 [Final] 기말고사
시스템 생명 주기(System Life Cycle)(1/2)
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
제 6장. 생성자와 소멸자 학기 프로그래밍언어및실습 (C++).
자료구조 김현성.
Chapter 02 순환 (Recursion).
5장. 참조 타입.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
8장 함수 함수의 필요성 라이브러리 함수와 사용자 정의 함수 함수의 정의, 원형, 호출 배열을 함수 인자로 전달 재귀호출.
SqlParameter 클래스 선문 비트 18기 발표자 : 박성한.
컴퓨터 프로그래밍 기초 #02 : printf(), scanf()
정적 멤버 변수/정적 멤버 함수 - friend 함수/클래스 template
C++ Espresso 제12장 템플릿.
프로그래밍 랩 – 7주 리스트.
14장. 포인터와 함수에 대한 이해.
11장. 1차원 배열.
C#.
13. 연산자 오버로딩.
Method & library.
JA A V W. 03.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
어서와 C언어는 처음이지 제14장.
자료구조: CHAP 7 트리 –review 순천향대학교 컴퓨터공학과 하 상 호.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
Quiz #7 다음 수들을 합병 정렬과 퀵 정렬 알고리즘을 이용하여 오름 차순으로 정렬하였을 때, 데이터 이동 회수를 각각 구하라. 여러분은 정렬 과정을 단계별로 보이면서 이동 회수를 추적해야 한다. 단, 퀵 정렬시에 피봇으로 배열의 왼쪽 첫 번째 원소를 선택한다. 5.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
Lesson 2. 기본 데이터형.
제1장 자료구조를 배우기 위한 준비.
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
2장. 변수와 타입.
선택 정렬 #define SWAP(x, y, t) {(t) = (x); (x) = (y); (y) = (t);}
제 1 강.
제 4장. 객체 지향 프로그래밍 시작하기 학기 프로그래밍언어및실습 (C++).
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
Canary value 스택 가드(Stack Guard).
함수(Function) ◈ 함수의 개념 및 사용 이유 ◈ 함수 정의, 호출 및 선언 ◈ 지역변수와 전역변수 ◈ return 문
알고리즘 알고리즘이란 무엇인가?.
제 6 장 함수(functions).
데이터 동적 할당 Collection class.
알고리즘 분석 알고리즘 정의 알고리즘 요건(Criteria) 특정한 일을 수행하기 위한 명령어의 유한 집합
4장. 데이터 표현 방식의 이해. 4장. 데이터 표현 방식의 이해 4-1 컴퓨터의 데이터 표현 진법에 대한 이해 n 진수 표현 방식 : n개의 문자를 이용해서 데이터를 표현 그림 4-1.
DA :: 퀵 정렬 Quick Sort 퀵 정렬은 비교방식의 정렬 중 가장 빠른 정렬방법이다.
7주차: Functions and Arrays
제 8장. 클래스의 활용 학기 프로그래밍언어및실습 (C++).
쉽게 배우는 알고리즘 2장. 점화식과 점근적 복잡도 분석
발표자 : 이지연 Programming Systems Lab.
컴퓨터 프로그래밍 기초 - 9th : 배열 / 포인터 -
실습과제 (변수와 자료형, ) 1. 다음 작업 (가), (나), (다)를 수행하는 프로그램 작성
제 4 장 Record.
29장. 템플릿과 STL 01_ 템플릿 02_ STL.
어서와 C언어는 처음이지 제21장.
개정판 누구나 즐기는 C언어 콘서트 제13장 동적 메모리 출처: pixabay.
C++ Espresso 제15장 STL 알고리즘.
7 생성자 함수.
6 객체.
2019 2학기 9장 배열과 포인터 1. 주소, 주소연산자(&) 2. 포인터, 역참조연산자(*) 3. 배열과 포인터.
Presentation transcript:

Chapter 1 Basic Concepts 2009. 3. 16

알고리즘(Algorithm) 특정한 일을 수행하기 위한 명령어들의 유한 집합 알고리즘의 요건(criteria) 1. 입력 : (외부) 원인  0 2. 출력 : 결과  1 3. 명확성(definiteness) : 모호하지 않은 명확한 명령 4. 유한성(finiteness) : 반드시 종료 5. 유효성(effectiveness) : 각 명령은 기본적이고 실행 가능해야 함 알고리즘 기술 방법 자연어 기술 흐름도(flowchart) Pseudo-code Programming Language (예: C 언어)

알고리즘의 기술 (예 1.1) [선택 정렬] : n  1 개의 서로 다른 정수의 집합을 정렬하는 프로그램을 작성 방법: 정렬되지 않은 정수들 중에서 가장 작은 값을 찾아서 정렬된 리스트 다음 자리에 놓음 예: 3, 8, 1, 4, 7  1, 8, 3, 4, 7  1, 3, 8, 4, 7  1, 3, 4, 8, 7  1, 3, 4, 7, 8 for (i = 0; i < n; i++) [ list[i]에서부터 list[n-1]까지의 정수 값을 검사한 결과 list[j]가 가장 작은 값이라 하자; list[i]와 list[j]를 서로 교환함; }

선택 정렬 프로그램 void SelectionSort(int *list, const int n) // n개의 정수 list[0]부터 list[n-1]까지 비감소 순으로 정렬함. { for (int i = 0; i < n; i++) { int temp, min; // list[min]과 list[n-1] 사이의 가장 작은 정수 찾음 min = i; for (int k = i + 1; k < n; k++) if (list[k] < list[min]) min = k; temp = list[i]; list[i] = list[min]; list[min] = temp; // 교환 } 0 1 2 3 4 3, 8, 1, 4, 7  1, 8, 3, 4, 7  1, 3, 8, 4, 7  1, 3, 4, 8, 7  1, 3, 4, 7, 8

알고리즘의 기술 (예 1.2) [이진 탐색] : x = list[j]인 j를 찾음 가정: list의 원소들은 이미 정렬된 상태 left, right: 탐색하고자 하는 원소들의 왼쪽 및 오른쪽 끝 지점 초기 값: left = 0, right = n-1 middle: 탐색할 원소들의 중간 위치, 즉, middle = (left + right) / 2 list[middle]과 x를 비교할 경우 3가지 경우 중에 하나 ⑴ x > list[middle] 일 때: left를 middle+1로 설정 ⑵ x < list[middle] 일 때: right를 middle-1로 설정 ⑶ x = list[middle] 일 때: middle을 반환 left middle right 0 1 2 3 4 5 6 7 8 9 10 3 5 7 10 15 16 19 20 26 28 31 index list x = 26

이진 탐색 알고리즘 int BinarySearch(int *list, const int x, const int n) // 정렬된 배열 list[0], ..., list[n-1]에서 x를 탐색한다. { for (left와 right를 초기화한다; 원소가 더 있는 한 계속; ) // 가운데 원소를 middle로 설정한다. switch (compare(x, list[middle])) { case '>' : left를 middle + 1로 설정; break; case '<' : right = middle - 1로 설정; break; case '=' : x를 발견; } not found; char compare(int x, int y) { if (x > y) return '>'; else if (x < y) return '<'; else return '='; }

이진 탐색 함수 구현 int BinarySearch(int *list, const int x, const int n) // 정렬된 배열 list[0], ..., list[n-1]에서 x를 탐색한다. { for (int left = 0, right = n-1; left <= right; ) { int middle = (left + right) / 2; switch (comare(x, list[middle])) { case '>' : left = middle + 1; break; // x > list[middle] case '<' : right = middle - 1; break; // x < list[middle] case '=' : return middle; // x == list[middle] } return -1; // x가 list에 존재하지 않음

순환 알고리즘(Recursive Algorithms) 수행이 완료되기 전에 자기 자신을 다시 호출 직접 순환 : direct recursion 간접 순환 : indirect recursion 예 Factorial(!) : N! = N*(N-1)! 이항 계수(Binomial Coefficient) Fibonacci 수열 int FACT(int N) { if (N==0) return (1); else return (N*FACT(N-1)); } N*(N-1)*(N-2)*....*2*1*1

순환 알고리즘(Recursive Algorithms) 특징 장점: 실행 과정의 효율적 기술 복잡한 계산 과정을 단순하고 명료하게 표현 가능 문제 자체가 순환적으로 정의되는 경우에 적합 단점: 실행 효율 저하 실행 시간에 순환을 위한 별도의 준비 설정이 필요 공간 및 시간 복잡도 증가 일반적으로 배정문(assignment), 조건문(if-else), 반복문(while)으로 표현되는 반복 알고리즘은 순환 알고리즘으로 변환 가능

예1.3: 이진 탐색의 순환적 구현 int BinarySearch(int *list, const int x, const int left, const int right) // 정렬된 배열 list[left], ..., list[right]에서 x를 탐색 { if (left <= right) { int middle = (left + right) / 2; switch(compare(x, list[middle])) { case '>' : return BinarySearch(list, x, middle+1, right); case '<' : return BinarySearch(list, x, left, middle-1); case '=' : return middle; } return -1; // x가 발견되지 않음

예1.4: 순열 생성기 n1개의 원소로 된 집합으로부터 모든 가능한 순열을 출력 perm(a, b, c, d); 1) a + perm(b, c, d) 2) b + perm(a, c, d) 3) c + perm(b, a, d) 4) d + perm(b, c, a) perm(b, c, d) 1) b + perm(c, d) 2) c + perm(b, d) 3) d + perm(c, b) perm(c, d) 1) c + perm(d) 2) d + perm(c)

예1.4: 순열 생성기 void perm(char *list, const int k, const int n) { // n은 list의 크기 // list[k], ..., list[n-1]에 대한 모든 순열을 생성 if (k == n-1) { // 순열을 출력 for (int i = 0; i < n; i++) printf(“%c”, list[i]); printf(“\n”); } else{ // list[k], ..., list[n-1]에 있는 여러 순열을 순환적으로 생성 for (i = k; i < n; i++) { // list[k]와 list[i]를 교환 char temp = list[k]; list[k] = list[i]; list[i] = temp; perm(list, k+1, n); // list[k+1], ..., list[n-1]에 대한 모든 순열 // 원래 상태로 되돌리기 위해 list[k]와 list[i]를 다시 교환 temp = list[k]; list[k] = list[i]; list[i] = temp; } } perm(list, 0, n) 호출  list[0], list[1], …, list[n-1]에 대한 모든 순열 생성

데이터 타입(Data Type) 정의 C/C++의 데이터 타입 객체(object)와 그 객체 위에 작동하는 연산(operation)들의 집합 사전 정의(pre-defined) 데이터 타입 사용자 정의(user-defined) 데이터 타입 C/C++의 데이터 타입 기본 데이터 타입 char, int, float, double 타입 수식어: short, long, signed, unsigned 파생 데이터 타입 포인터(pointer) 타입, 참조(reference) 타입(C++) 데이터 집단화 구조 배열(array), 구조체(struct), 클래스(class)(C++)

데이터 캡슐화 및 추상화 데이터 캡슐화(Encapsulation) 데이터 추상화 외부에 대해 데이터 객체의 자세한 구현을 은폐시킴 객체의 내부 표현을 사용자로부터 은폐 (information hiding) 데이터 추상화 데이터 객체의 명세(specification)와 구현(implementation) 을 분리 “무엇(what)”과 “어떻게(how)”를 독립화 추상 데이터 타입(Abstract Data Type: ADT) 객체와 연산에 대한 명세를 객체의 표현 및 연산의 구현으로부터 분리시킨 데이터 타입 예: Ada언어의 Package, C++/Java언어의 Class ADT 연산의 명세 함수 이름, 매개 변수 타입, 결과 타입, 함수가 수행하는 기능에 대한 기술 내부적 표현이나 구현에 대한 자세한 설명은 제외됨

예: 자연수(Natural Number) 추상 데이터 타입 정의 예 ADT NaturalNumber is 객체: 순서가 있는 정수의 일부분으로 0부터 해당 컴퓨터의 최대 정수(MAXINT)까지의 값 함수: x, y  NaturalNumber, TRUE, FALSE  Boolean +, -, <, ==, = 는 일반 정수 연산자 Zero():NaturalNumber ::= 0 IsZero(x):Boolean ::= if (x == 0) IsZero = TRUE else IsZero = FALSE Add(x,y):NaturalNumber ::= if (x+y <= MAXINT) Add = x+y else Add = MAXINT Subtract(x,y):NaturalNumber ::= if (x<y) Subtract = 0 else Subtract = x-y Equal(x,y):Boolean ::= if (x == y) Equal = TRUE else Equal = FALSE Successor(x):NaturalNumber ::= if (x == MAXINT) Successor = x else Successor = x+1 end NaturalNumber

Stack ADT의 예 (C++) #include <iostream.h> class stack { // stack class 정의 private: int* stackPtr; int maxLen, topPtr; public: stack() { // constructor stackPtr = new int [100]; maxLen = 99; topPtr = -1; } ~stack() { delete[] stackPtr; } //destructor void push(int number); void pop(); int top() { return stackPtr[topPtr]; } int empty() { return (topPtr == -1); }

Stack ADT의 예 (C++) stack 클래스 이용 예 표준 C++ 라이브러리(standard C++ library) ISO 및 ANSI 표준 (ISO/IEC 14882) STL(Standard Template Library) 표준 데이터 구조에 대한 클래스 정의와 이러한 데이터 구조에 대한 주요 알고리즘 정의 http://oopsla.snu.ac.kr/~sjjung/stl/ 참조 void main() { int topOne; stack stk; // stack 클래스의 instance 생성 stk.push(42); stk.push(17); topOne = stk.top(); stk.pop(); … }

데이터 추상화 및 캡슐화의 장점 소프트웨어 개발의 간소화 검사와 디버깅의 단순화 재사용성 향상 데이터 타입 표현의 수정 용이 복잡한 작업을 여러 부분 작업들로 분해 검사와 디버깅의 단순화 부분 작업 재사용성 향상 자료 구조가 소프트웨어 시스템에서 독립적인 객체들로 구현되어 재사용 가능 데이터 타입 표현의 수정 용이 데이터 타입의 내부 구현을 직접 접근하는 부분만 변경 필요 그 이외 부분에는 무관 프로그램의 신뢰성 증가 객체는 ADT에서 제공되는 연산을 통해서만 변경 가능하므로 객체의 무결성 보장

성능 분석 및 측정 프로그램에 대한 평가 성능 평가 평가 기준 사전 예측  성능 분석(performance analysis) 명세에 부합 여부 정확히 작동 여부 문서화 논리적 작업 단위를 위한 함수의 효과적 이용 성능 평가 사전 예측  성능 분석(performance analysis)  시간과 공간의 추산 복잡도 이론(complexity theory) 이용 사후 검사  성능 측정(performance measurement)  컴퓨터 의존적인 실행 시간 측정 코드의 판독 용이성 메모리의 효율적 사용 적절한 실행 시간

성능 분석: 공간 복잡도 공간 복잡도(space complexity) S(P) = c + SP(I) 프로그램을 완전히 실행하는데 필요한 공간(메모리)의 양 고정 부분 프로그램 입출력 횟수나 크기와 관계없이 고정됨 예: 프로그램 코드, 단순 변수, 고정크기의 구조화 변수, 상수 등 가변 부분 입/출력의 수, 크기, 값 등 문제의 인스턴스(instance)의 특성에 의존 예: 가변 집단 변수, 순환 호출을 위한 스택 공간 등 프로그램 P의 공간 요구량 S(P) = c + SP(I) c : 상수(고정 부분에 해당) SP(I) : P의 인스턴스 I 에 의한 가변 공간 요구량

공간 복잡도 계산 예 예1.6: 단순 산술 함수 예1.7: 수치값 리스트 합산 함수 (반복적 구현) float abc(float a, float b, float c) {     return a+b+b*c + (a+b-c) / (a+b) + 4.00; } 고정 공간 요구만을 가짐 => Sabc(I) = 0 예1.7: 수치값 리스트 합산 함수 (반복적 구현) float sum(float list[], int n) {    float tempsum = 0;    int i;    for (i = 0; i < n; i++)       tempsum += list[i];    return tempsum; } 가변 공간 요구 : 배열 (크기 n) - 함수에 대한 배열의 전달 방식에 따라 다름  - 배열 전체의 복사 전달 (예: Pascal)         . Ssum(I) = Ssum(n) = n  - 배열의 첫번째 요소의 주소 전달 (예: C)         . Ssum(n) = 0

공간 복잡도 계산 예 예1.8: 수치값 리스트 합산 함수 (순환적 구현) float rsum(float list[], int n) {     if (n) return rsum(list, n-1) + list[n-1];     return 0; } - 함수 호출시 마다 매개 변수, 지역 변수, 복귀 주소를 저장해야 함 - 한번의 순환 호출을 위해 요구되는 공간   두 개의 매개 변수와 복귀 주소를 저장하기 위한 바이트 수                              ↱ list[]의 주소                       =  2    +    4    +    4  = 10                 ↳ sizeof(n)      ↳ 복귀주소 n = MAX_SIZE 일 때,           Srsum(MAX_SIZE) = 10 * MAX_SIZE

성능 분석: 시간 복잡도 시간 복잡도(time complexity) T(P) = c + TP(I) 프로그램을 완전히 실행시키는데 필요한 컴퓨터 시간의 양 프로그램에 의한 소요 시간 예: 산술 연산 프로그램 n: 인스턴스 특성 Ca, Cs, Cm, Cd : +, -, x, / 연산을 위한 상수 시간 ADD, SUB, MUL, DIV : 인스턴스 특성 n에 대한 연산 실행 횟수 T(P) = c + TP(I) c: 컴파일 시간  고정값 TP(I): 실행시간  인스턴스 특성 I에 따라 다름 TP(n) = Ca*ADD(n) + Cs*SUB(n) + Cm*MUL(n) + Cd*DIV(n)

성능 분석: 시간 복잡도 프로그램이 수행하는 연산의 횟수로 시간 복잡도를 추정 프로그램 단계(step) 프로그램 단계 수 (step count) 프로그램 단계(step) 실행 시간이 인스턴스 특성에 구문적으로나 의미적으로 독립성을 갖는 프로그램의 단위(세그먼트) 각 단계의 실행에 필요한 시간이 인스턴스 특성에 독립적이어야 함 예: 입력의 수 n에 대한 시간 복잡도 계산 시, n개의 정수들의 덧셈은 한 단계가 될 수 없음 각 단계의 실제 계산량은 서로 상이할 수 있음 예: a = 2; a = 2*b+c;

예1.9: 수치값 리스트 합산 함수 (반복) 2n+3 1. Counter 이용 float sum(float *list, const int n) { float s = 0; count++; // 배정문 for (int i = 0; i < n; i++) { count++; // for문 s += list[i]; count++; // 배정문 } count++; // for문의 마지막 실행 return s; count++; // return문 float sum(float *list, const int n) for (int i = 0; i < n; i++) count += 2; count += 3; 2n+3

예1.9: 수치값 리스트 합산 함수 (반복) 2. 단계수 Table 작성 행번호 s/e 빈도수 총 단계수 1 0 1 0 2 1 1 1 3 1 n+1 n+1 4 1 n n 5 1 1 1 6 0 1 0 tsum(n) = 2n+3 float sum(float *list, const int n) 1 { 2 float s = 0; 3 for(int i = 0; i < n; i++) 4 s += list[i]; 5 return s; 6 }

예1.10: 수치값 리스트 합산 함수 (순환) 단계 수 계산 float rsum(float *list, const int n) 1 { 2 if (n <= 0) return 0; 3 else return (rsum(list, n-1)+list[n-1]); 4 } 단계 수 계산 trsum(n) = 2 + trsum(n-1) = 2 + 2 + trsum(n-2) = 2 * 2 + trsum(n-2) … = 2n + trsum(0) = 2n + 2

시간 복잡도 계산 예 행렬의 덧셈 문 장 s/e 빈도수 총단계수 void add(int a[][MAX_SIZE] ··· ) { 문 장 s/e 빈도수 총단계수 void add(int a[][MAX_SIZE] ··· ) { int i, j; for (i=0, i<rows; i++) for(j=0, j<cols; j++) c[i][j] = a[i][j] + b[i][j] } 0 0 0 1 rows+1 rows+1 1 rows(cols+1) rows·cols+row 1 rows·cols rows·cols 합 계 2rows·cols+2rows+1

성능 분석: 시간 복잡도 프로그램 단계 수 프로그램 인스턴스 특성에 대한 함수 여러가지 특성들 중 관심이 있는 특성들에 대한 함수로 표현 예: 입력의 수의 증가에 대한 시간 복잡도, 특정 입력의 크기가 증가함에 따른 시간 복잡도 등 주어진 인스턴스 특성에 대해 단계 수를 유일하게 결정할 수 없는 경우 예: binary search 원소의 수 n 외에, 탐색 키의 위치에 따라 단계수가 달라짐 최악의 경우(worse-case), 최선의 경우(best-case), 평균(average-case) 단계 수 계산

점근 표기법(O, , ) Motivation 프로그램의 정확한 단계 수 계산 : 어렵고 무의미함 근사치 사용 동일 기능의 두 프로그램의 시간 복잡도 비교 인스턴스 특성의 변화에 따른 실행 시간 증가 예측 프로그램의 정확한 단계 수 계산 : 어렵고 무의미함 예: A의 단계수 = 3n + 3, B의 단계수 = 100n + 10 A ≃ 3n (or 2n), B ≃ 100n (or 80n, 85n) 근사치 사용  C1과 C2가 음이 아닌 상수일 때, C1n2 ≤ Tp(n) ≤ C2n2 또는 TQ(n,m) = C1n + C2m 등으로 표현 가능 충분히 큰 n에 대해 C1n2 + C2n > C3n 성립 예) C1= 1, C2 = 2, C3 = 100이고, n ≤ 98일때, C1n2 + C2n ≤ C3n, n  > 98일때, C1n2 + C2n  > C3n 즉, 손익분기점(break even point)은 n = 98 C1, C2, C3 및 손익분기점을 정확히 알아낼 필요는 없음

점근 표기법(O, , ) 정의: [Big "oh"] f(n) = Ο(g(n))  ∃c,n0 > 0, s.t. f(n) ≤ cg(n) for ∀n, n≥n0 예 n ≥ 2,  3n + 2 ≤ 4n ⇨  3n + 2 = Ο(n) n ≥ 3, 3n + 3 ≤ 4n ⇨  3n + 3 = Ο(n) n ≥ 10, 100n + 6 ≤ 101n  ⇨ 100n + 6 = Ο(n) n ≥ 5, 10n2 + 4n + 2 ≤ 11n2 ⇨ 10n2 + 4n + 2 = Ο(n2) n ≥ 4, 6*2n + n2 ≤ 7*2n ⇨  6*2n + n2 = Ο(2n) n ≥ 2, 3n + 3 ≤ 3n2 ⇨  3n + 3 = Ο(n2) n ≥ 2, 10n2 + 4n + 2 ≤ 10n4  ⇨  10n2 + 4n + 2 = Ο(n4) n ≥ n0인 모든 n과 임의의 상수 c에 대해, 3n + 2 ≤ c 가 false인 경우가 존재하므로 ⇨  3n+2≠Ο(1) 10n2 + 4n + 2 ≠ Ο(n)

점근 표기법(O, , ) order of magnitude O(1) : 상수(constant) O(log logn) : log log O(logn) : logarithmic O(n) : 선형(linear) O(nlogn) : log linear O(n2) : 평방형(quadratic) O(n3) : 입방형(cubic) O(2n) : 지수형(exponential) O(n!) : factorial

점근 표기법(O, , ) f(n) = Ο(g(n)) n ≥ n0인 모든 n에 대해 g(n) 값은 f(n)의 상한 값이라는 것을 의미 예: 3n+3 = O(n), 3n+3 = O(n2), 3n+3 = O(2n) 일반적으로 g(n)은 조건을 만족하는 가장 작은 함수여야 함 예: 3n+3 = O(n)으로 표현 정리: f(n) = amnm + … + a1n1+ a0  f(n) = O(nm) f(n) = O(g(n))  for some c R*

점근 표기법(O, , ) 정의: [Big "Omega"] f(n) = Ω(g(n))  ∃c,n0 > 0, s.t. f(n) ≥ cg(n) for ∀n, n≥n0 예 n ≥ 1, 3n + 2 ≥ 3n ⇨ 3n + 2 = Ω(n) n ≥ 1, 3n + 3 ≥ 3n ⇨ 3n + 3 = Ω(n) n ≥ 1, 100n + 6 ≥ 100n ⇨ 100n + 6 = Ω(n) n ≥ 1, 10n2 + 4n + 2 ≥ n2 ⇨ 100n2 + 4n + 2 = Ω(n2) n ≥ 1, 6*2n + n2 ≥ 2n ⇨ 6*2n + n2 = Ω(2n)

점근 표기법(O, , ) f(n) = Ω(g(n)) n ≥ n0인 모든 n에 대해 g(n) 값은 f(n)의 하한값이라는 것을 의미 예: 3n2+3 = Ω(n2), 3n2+3 = Ω(n), 3n2+3 = Ω(1) 일반적으로 g(n)은 조건을 만족하는 가장 큰 함수여야 함 예: 3n2+3 = Ω(n2)으로 표현 f(n) = Ω(g(n))  or

점근 표기법(O, , ) 정의: [Theta] f(n)=Θ(g(n))  ∃C1,C2,n0 > 0, s.t. C1g(n)≤f(n)≤C2g(n) for ∀n, n≥n0 예 n ≥ 2, 3n ≤ 3n + 2 ≤4n ⇨ 3n + 2 = Θ(n)  c1 = 3, c2 = 4, n0 = 2 3n + 3 = Θ(n) 10n2 + 4n + 2 = Θ(n2) 6*2n + n2 = Θ(2n)       10*log n + 4 = Θ(log n)

점근 표기법(O, , ) f(n)=Θ(g(n)) g(n)이 f(n)에 대해 상한 값과 하한 값을 모두 가지는 경우 f(n) = Θ(g(n))  for some c R+

점근 표기법(O, , ) 점근적 복잡도(asymptotic complexity: Ο,Ω,Θ) 정확한 단계수의 계산없이 쉽게 구할 수 있음 예: sum(float *a, const int n) float sum(float *a, const int n) 1 { 2 float s = 0; 3 for(int i = 0; i < n; i++) 4 s += list[i]; 5 return s; 6 } 행번호 s/e 빈도수 총 단계 1 0 0 Θ(0) 2 1 1 Θ(1) 3 1 n+1 Θ(n) 4 1 n Θ(n) 5 1 1 Θ(1) 6 0 1 Θ(0) tsum(n) = Θ(max{gi(n)}) = Θ(n)

점근 표기법(O, , ) 예제 [이진 탐색] 예제 [순열] 예제 [Magic Square] Worst-cast: Θ(log n) Best-case: Θ(1) 예제 [순열] Θ(n(n!)) 예제 [Magic Square] Θ(n2)

매직 스퀘어 15 8 1 24 17 16 14 7 5 23 22 20 13 6 4 3 21 19 12 10 9 2 25 18 11 매직 스퀘어의 예

void magic(int n) // 크기가 n이고 n은 홀수인 매직 스퀘어를 생성 { const int MaxSize = 51; // 스퀘어의 최대 크기 int square[Max_Size][Max_Size], k, l; // n이 올바른 값인지 검사 if((n > (Max_Size)) || (n < 1)){ cerr << "Error! ... n out of range" <<endl; return; } else if(!(n%2)) { cerr << "Error! ... n is even" << endl; return; // n이 홀수. Coxeter의 규칙이 사용됨 for(int i = 0; i < n; i++) // square를 0으로 초기화 for(int j = 0; j < n; j++) square[i][j] = 0; square[0][(n-1)/2] = 1; // 첫 행의 중간 // i와 j는 현재 위치 int key = 2; i = 0; int j = (n-1)/2;

while(key <= n * n){ // 왼쪽 위로 이동 if(i - 1 < 0) k = n - 1; else k = i - 1; if(j - 1 < 0) l = n - 1; else l = j - 1; if(square[k][l]) i = (i + 1) % n; // square가 채워짐. 아래로 이동 else{ // square[k][l]이 채워지지 않음 i = k; j = l; } square[i][j] = key; key++; // 매직 스퀘어를 출력 cout << "magic square of size" << n << endl; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) cout << square[i][j] << " "; cout << endl;

실용적 복잡도 매우 큰 n에 대해서는, 작은 시간 복잡도를 가진 프로그램(알고리즘)만이 실제적으로 사용 가능함

실용적 복잡도 If a program needs 2n steps for execution, n=40 --- number of steps = 1.1*1012 in computer systems performing 1 billion steps/sec --- 18.3 min n=50 --- 13 days n=60 --- 310.56 years n=100 --- 4*1013 years