Transcript 제 1 장 기본 개념
자료 구조
제 1 장 : 기본 개념
이형원
강릉대학교 컴퓨터공학과
학습 내용
소프트웨어 개발 단계
알고리즘이란 무엇인가 ?
데이터 추상화
알고리즘의 성능 분석 방법
2
시스템 생명 주기
1. 타당성 조사(feasibility study)
2. 계획(planning)
3. 요구 사항 분석(requirement analysis)
요구사항에 기초하여 무엇을 개발할 것인가 결정
문제를 실제 다룰수 있을 정도의 작은 단위로 나눔
4. 설계(design)
data objects와 operations을 설계
구현에 관한 사항은 뒤로 미룸
5. 코딩(coding)
3
data object에 대한 표현을 선택, algorithm 구현
시스템 생명 주기(계속)
6. 검증(verification)
정확성 증명 : 수학적 기법 이용
• time consuming, difficult to develop for large projects
• 증명된 algorithm/program은 확실 --> 오류를 줄임
테스트 : 프로그램의 정확한 수행 검증
• 모든 가능한 경우를 포함하는 테스트 data가 필요
• 논리적 오류 & running time
• 단위 테스트, 통합 테스트
발견된 오류를 제거 : 분석, 설계 단계가 중요
• spaghetti code vs. structured code
– readability & understandability
– error from error correction
4
알고리즘
특정 일을 수행하는 명령어들의 유한 집합
algorithm의 조건
⑴ 입력 : 외부에서 제공되는 데이타가 0개 이상
⑵ 출력 : 적어도 한가지의 결과를 생성
⑶ 명확성 : 각 명령은 모호성이 없어야 함
⑷ 유한성 : ① 한정된 수의 단계 후 반드시 종료
② 수행 시간의 현실적인 유한성
⑸ 유효성 : 모든 명령은 실행 가능해야 함
기술 방법
자연어(명확성 유의), 다이어그램, 의사 코드, HLL
5
예제 [이진탐색] : 요구 사항
요구 사항
list[0] ≤ list[1] ≤ ...≤ list[n-1] where list[i] is integer
정수 searchnum이 배열 list에 있는지 검사
• searchnum에 대해 list[i] = searchnum인 인덱스 i를 반환
• 없는 경우는 -1 반환
선형탐색 vs. 이진탐색
6
예제 [이진탐색] :알고리즘 1
while (there are more integers to check) {
middle = (left + right) / 2;
if (searchnum < list[middle]) right = middle - 1;
else if (searchnum == list[middle]) return
middle;
else left = middle + 1;
}
비교 연산 : 함수 or 매크로
#define COMPARE(x,y) ((x) < (y)) ? -1 : ((x) == (y))7 ? 0 :
1)
예제 [이진탐색] :알고리즘 2
int binsearch(int list[], int searchnum, int left, int right)
{
int middle;
while (left<=right) {
middle = (left + right)/2;
switch (COMPARE(list[middle], searchnum))
{
case -1: left = middle + 1; break;
case 0: return middle;
case 1: right = middle - 1;
}
}
8
return -1;
순환 알고리즘 : 정의와 특성
순환 : 자기 자신을 사용하는 알고리즘
예) 계단 오르기
더 이상 계단이 없으면 멈춤
계단을 하나 올라감
계단 오르기
종류
• direct recursion : 함수의 수행이 완료되기 전에 자신을 다시 호출
• indirect recursion : 호출 함수를 다시 호출하는 다른 함수를 호출
특성
• 배정/if-else/while문으로 작성가능한 어떤 program도 순환 사용 가
능
• 문제 자체가 순환적으로 정의된 경우 유용
– Fibonacci 수 : Fn = Fn-1 + Fn-2 where F0 = 0 , F1 = 1, and n 2
9
– factorial : n! = n * (n-1)!
순환 알고리즘 : 예제 [이진 탐색]
int binsearch(int list[], int searchnum, int left, int right) {
int middle;
if (left <= right) {
middle = (left + right) / 2;
switch (COMPARE(list[middle], searchnum)) {
case -1: return binsearch(list, searchnum, middle+1,
right);
case 0: return middle;
case 1: return binsearch(list, searchnum, left,
middle-1);
}
}
return -1;
10
}
데이타 추상화 : data type의 종류
C 언어의 data type
기본 data type : char, int, float, double
키워드 : short, long, unsigned
자료의 그룹화(user-defined data type) : 배열, 구
조
• int list[5]
• struct student {
char last_name;
int student_id;
char grade;
};
포인터 data type
11
데이타 추상화 : What is data
type ?
객체(data)와 그 객체에 작동하는 연산의 집합
예) data type int
• 객체 : {0, ±1, ±2, ±3, ...., INT_MAX, INT_MIN}
• 연산 : +, -, *, /, %, 배정, 테스트
객체의 표현
• char 형 : 1 바이트 비트열
• int 형 : 2 또는 4 바이트(2 바이트 경우 INT_MAX = 215-1)
• 구체적 내용을 사용자가 모르도록 하는 것이 좋은 방법
객체 구현 내용에 대한 알고리즘의 독립성
12
데이타 추상화 : ADT
Abstract Data Type(ADT)
data type의 논리적 정의
• 객체와 연산의 본질(what)에 대한 명세만 정의
• 객체의 표현과 연산의 구현(how)은 배제
명 시 적
지 원
C++/JAVA(class)
ADT 연산의 명세
언 어
:
Ada(package),
• 함수의 이름, 매개 변수형, 결과형, 기능
• 내부적 표현/구현에 대한 자세한 설명은 필요 없음
구현에 독립
• 이를 바탕으로 알고리즘 작성
13
데이터 추상화 : 예
structure Natural_Number
objects : 0 ~ 컴퓨터상의 최대 정수 값(INT_MAX)까지
순서화된 정수의 부분 범위이다.
functions : x, y Nat_Number and TRUE, FALSE
Boolean
Nat_No Zero()
Boolean Is_Zero(x)
Nat_No Add(x, y)
::= 0
::= if (x) then FALSE else return TRUE
::= if ((x+y)<=INT_MAX) return x+y
else return INT_MAX
::= if (x==y) return TRUE else return
Boolean Equal(x,y)
FALSE
Nat_No Succesor(x) ::= if (x==INT_MAX) return x else return
x+1
Nat_No Subtract(x,y) ::= if (x<y) return 0 else return x-y 14
end Natural_Number
성능 분석
프로그램 판단의 기준
프로그램이 원래의 명세와 부합하는가 ?
정확하게 작동하는가 ?
프로그램의 코드가 읽기 쉬운가 ?
…..
nonquantitative
성능 평가(performance evaluation)
성능 분석(복잡도 이론): 컴퓨터에 관계없이 시간/공간 추산
• 공간 복잡도 : 프로그램을 실행시켜 완료하는 데 필요한 공간의 양
• 시간 복잡도 : 프로그램을 실행시켜 완료하는 데 필요한 시간의 양
성능 측정: 실제로 컴퓨터에서의 수행 시간을 얻음
15
공간 복잡도
프로그램에 필요한 공간
고정 공간 요구
• Program 입출력의 횟수나 크기에 관계없는 memory 요
구
– 명령어 공간(코드저장을 위한 공간)
– 단순 변수, 고정 크기의 구조화 변수, 상수들을 위한 공간
가변 공간 요구 SP(I)
• 문제의 특정 인스탄스 I에 따라 변하는 memory 요구
• 인스탄스 특성 : 입출력의 횟수/크기/값
예) 입력이 n개의 요소를 갖는 배열 : n
• 공간 복잡도 분석 : 가변 공간 요구에만 관심
16
공간 복잡도 : 예제 abc
float abc(float a, float b, float c) {
return a+b+b*c + (a+b-c) / (a+b) + 4.00;
}
Q. Sabc(I) = ?
17
공간 복잡도 : 예제 sum
float sum(float list[], int n) {
float tempsum = 0; int i;
for (i = 0; i < n; i++) tempsum += list[i];
return tempsum;
}
Q. Ssum(I) = Ssum(n) = ?
18
공간 복잡도 : 예제 rsum
float rsum(float list[], int n) {
if (n) return rsum(list, n-1) + list[n-1];
return 0;
}
반복 함수보다 overhead가 큼 Q. Why ?
Srsum(n) = 한 번의 순환 호출을 위해 요구되는 공간 * n
= 2개의 매개 변수, 복귀 주소를 위한 바이트 수 *
n
= (list[]의 주소 + sizeof(n) + 복귀주소) * n
= (2 + 2 + 2) * n = 6n
19
시간 복잡도
실행 시간의 획득 방법
1) 시스템 클럭을 사용
2) 프로그램 단계 수(program step count)를 계산
• 실행 시간이 인스턴스 특성에 관계없이 구문적으로 또
는 의미적으로 뜻을 갖는 프로그램의 단위
ex) a = 2
1 step !!
a = 2*b+3*c/d-e+f/g/a/b/c
• 한단계 실행에 필요한 시간이 인스턴스 특성에 독립적
이어야 함
20
시간 복잡도 : 단계수 계산
전역 변수 count의 삽입
예제 1.9 [수치 값 리스트의 합산을 위한 반복 호출]
float sum(float list[], int n) {
float tempsum = 0;
int i;
for (i = 0; i < n; i++) {
tempsum += list[i];
}
return tempsum;
}
Q. 단계수 ?
21
시간 복잡도 : 단계수 계산 (계속)
예제 1.10 [수치 값 리스트의 합산을 위한 순환 호출]
float rsum(float list[], int n){
count++;
/* if문을 위한 문장 */
if (n) {
count++;
/* 반환과 rsum의 호출을 위한 문장 */
return rsum(list, n-1) + list[n-1];
}
count++;
return list[0];
}
Q. 단계수 ?
Q. Titerative > Trecursive ??
22
시간 복잡도 : 단계수 계산 (계속)
예제 1.11 [행렬의 덧셈]
void add(int a[][MAX_SIZE], int b[][MAX_SIZE],
int c[][MAX_SIZE], int rows, int cols) {
int i, j;
for (i=0; i<rows; i++) { count++; /* i for루프문을 위한 문장
*/
for (j=0; j<cols; j++) { count++; /* j for루프문을 위한 문장
*/
c[i][j] = a[i][j] + b[i][j]; count++; /* 배정문을 위한 문장 */
} count++;
/* for루프에 대한 마지막 j */
} count++;
/* for루프에 대한 마지막 i */
}
단계수 = rows(2cols + 2) +1 = 2rows cols + 2rows +
23
시간 복잡도 : 단계수의 문제점
단계수 이용의 목적
동일 기능의 두 프로그램의 시간 복잡도 비교
인스턴스 특성의 변화에 따른 실행 시간 증가 예
측
But 단계수 결정은
• 어렵다
프로그램내에 코드를 삽입
• 부정확하다.
x= y 와 x= y+z+(x/y)*w-x/y는 같은 단계
정확한 실행 시간은 측정해야 알 수 있음
∴ 간단하고 유용한 복잡도 결정 방법이 필요
24
점근 표기법 Ο, Ω, Θ
가정 : f and g are nonnegative functions
f(n)=Ο(g(n)) iff c,n0 > 0, s.t f(n) ≤ cg(n) n≥n0
n ≥ 3, 3n + 3 ≤ 4 n ∴ 3n + 3 = Ο(n)
n0 f(n)
c g(n)
n ≥ 5, 10n2 + 4n + 2 ≤ 11n2 ∴ 10n2 + 4n + 2 = Ο(n2)
n ≥ 2, 3n + 3 ≤ 3n2 ∴ 3n + 3 = Ο(n2)
3n + 3 ≠Ο(1) 10n2 + 4n + 2 ≠ Ο(n)
least upper bound에 사용 : Q. 3n + 3 =Ο(n) or Ο(n2) ?
‘=’ means "is", not "equal”
Ο(1)<Ο(log n)<Ο(n)<Ο(n log n)<Ο(n2)<Ο(n3)<Ο(2n)
if f(n) = amnm + am-1nm-1 + ...+ a1n + a0,, then f(n) = Ο(nm)
25
점근 표기법 Ο, Ω, Θ(계속)
f(n)=Ω(g(n)) iff c,n0 > 0, s.t f(n)≥cg(n)
n≥n0
n ≥ 1, 3n + 2 ≥ 3n ∴ 3n + 2 = Ω(n)
n ≥ 1, 10n2 + 4n + 2 ≥ n2 ∴ 100n2 + 4n + 2 =
Ω(n2)
n ≥ 1, 6*2n + n2 ≥ 2n ∴ 6*2n + n2 = Ω(2n)
greatest lower bound: Q. 3n+2=Ω(n) or Ω(1) ?
if f(n) = amnm+…+a1n+a0, and am>0, then
f(n)=Ω(nm)
26
점근 표기법 Ο, Ω, Θ(계속)
f(n)=Θ(g(n))
iff c1,c2,n0>0, s.t c1g(n)≤f(n)≤c2g(n) n≥n0
n ≥ 2, 3n ≤ 3n + 2 ≤ 4n ∴ 3n + 2 = Θ(n)
10n2 + 4n + 2 = Θ(n2) ≠ Ο(n) ≠ Ο(n3)
both upper and lower bound
if f(n) = amnm+…+a1n+a0, and am>0, then
f(n)=Ω(nm)
27
점근 표기법 Ο, Ω, Θ(계속)
결론
보통 big oh 표기법만으로 복잡도를 표시(관행)
계수는 모두 1
점근 복잡도는 정확한 단계수의 계산없이 쉽게 구함
단계수 ==> 점근 복잡도
in program 1.10, Tsum(n) = 2n+3 ---> Tsum(n) = Θ(n)
in program 1.11, Trsum(n) = 2n+2 ---> Trsum(n) = Θ(n)
in program 1.14,
Tadd(rows,cols) = 2rows cols + 2rows + 1 =
Θ(rows.cols)
28
점근 표기법 Ο, Ω, Θ(계속)
프로그램 ==> 점근 복잡도
예제 [행렬 덧셈의 복잡도]
문 장
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
Θ(rows)
Θ(rows cols)
Θ(rows cols)
0
Θ(rows cols)
29
실용적인 복잡도
복잡도 함수의 용도
한 program의 인스턴스 특성 변화에 따른 변화 예
측
같은 작업을 수행하는 두 개의 program 비교
• P : Θ(n), Q : Θ(n2) --> 충분히 큰 n에 대해 P가 빠르다.
P : 106n msec, Q : n2 msec에 수행 & n ≤ 106
Q를 선택
함수들과 n의 관계: 그림 1.7, 그림 1.8, 그림
1.9
30
성능 측정 : 그림 1.10
Assignment
n!을 구하는 프로그램
반복문과 순환문을 이용하여 각각 작성
n = 100, 200, 300, …, 3000에 대해 실행 시간을
측정
점근 복잡도 계산
fibonacci 수 Fn을 구하는 프로그램
반복문과 순환문을 이용하여 각각 작성
n= 50, 100, 150, …, 1000에 대해 실행 시간을 측
정
31
점근 복잡도 계산