1 / 52

02. Recursion

02. Recursion. [INA240] Data Structures and Practice Youn-Hee Han http://link.kut.ac.kr. 0. Introduction. 프로세스 이미지 프로세스는 일정한 메모리를 배정 받아 사용 프로그램 실행에 필요한 어셈블러 코드 , 변수가 저장 원칙적으로 한 프로세스는 다른 프로세스의 메모리 영역에 접근 불가 C 프로그램과 이미지의 내용. #include <stdio.h> #include <stdlib.h>

amma
Download Presentation

02. Recursion

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 02. Recursion [INA240] Data Structures and Practice Youn-Hee Han http://link.kut.ac.kr

  2. 0. Introduction • 프로세스 이미지 • 프로세스는 일정한 메모리를 배정 받아 사용 • 프로그램 실행에 필요한 어셈블러 코드, 변수가 저장 • 원칙적으로 한 프로세스는 다른 프로세스의 메모리 영역에 접근 불가 • C 프로그램과 이미지의 내용 #include <stdio.h> #include <stdlib.h> extern char **environ; //extern 변수 int init_global_var = 3; //초기화된 global 변수 int uninit_global_var; //초기화되지 않은 global 변수 static int global_static_var; //static global 변수 int main(int argc, char **argv) { int auto_var; //automatic 변수 (local variable) static int local_static_var; //local_static 변수 register int reg_var; //register 변수 char *auto_ptr; //automatic 변수 (local variable) auto_ptr = (char *)malloc(10); return 0; } Data Structure

  3. 0. Introduction • 프로세스의 메모리 영역과 저장되는 변수 종류 Data Structure

  4. 0. Introduction Data Structure

  5. 0. Introduction • 다음코딩예의 출력 결과는? #include <stdio.h> void test(void) { static int s_count=0; int a_count=0; s_count++; a_count++; printf("static count=%d\tauto count=%d\n", s_count, a_count); } void main(void) { int i; for(i=0; i<5; i++) test(); } Data Structure

  6. 0. Introduction • 활성화 레코드 (Activation Record) • Activation Record is a chunk of computer memory which holds the arguments and local variables of the function. • Activation Record corresponds to a call to a function which has not yet terminated with a return. • 즉, 각 함수 호출시에 그 함수에서 선언된 모든 변수들의 기억장소를 포함하는 활성화 레코드(activation redord)를 생성한다. Data Structure

  7. 0. Introduction • main함수 호출에 따른 활성화 레코드 • int a;                  전역 변수 void main( ) { int b; char *s;       지역변수(스택) s = malloc(10);      10 바이트 동적변수(힙) b = fcn(5); free (s); } Data Structure

  8. 0. Introduction • main 함수에서 일반 함수 호출에 따른 활성화 레코드 • int a;                   void main( ) { int b; char *s;   s = malloc(10); b = fcn(5); free (s); } • int fcn(int p)  {   int b = 2;     b = b + p; return (b); } Data Structure

  9. 0. Introduction • Context Switching • 새로운 함수호출은 Context Switching 수반 • 새로운 활성화 레코드 생성 • 연속적인 함수호출에 따라 활성화 레코드 스택이 생성 • 함수 종료시 스택 상단의 활성화 레코드가 사라짐으로써 직전의 상황을 복원 • Stack Overflow • 무한 루프내에서 재귀적 함수 호출을 계속할 때 • Heap Overflow? • 무한 루프내에서 동적 메모리 할당을 계속 할 때 • 더 이상 할당할 힙 공간이 없을 때 NULL 을 반환 • 힙 메모리 소진을 대비한 코드nodePtr = (NODE*)malloc(sizeof(NODE)); if (nodePtr == NULL) ….. Data Structure

  10. 0. Introduction • Divide and Conquer (분할정복) • 문제의 크기 N • 큰 문제를 작은 문제로 바꿈 • 작은 문제 역시 큰 문제와 동일하다 • 문제의 크기만 다르다 • Base Case (베이스 케이스, 아주 작은 문제) • 직접 해결할 정도로 작아짐 • Degenerate Case • Recursive Call (재귀호출) • Self Call • 큰 문제를 분할 정복하여 풀다 보니 작은 문제를 풀 필요성이 생기고, 그 작은 문제 역시 원래 문제와 같은 스타일이기 때문에 자기자신의 포시져(함수) 호출이 필요하게 됨 Data Structure

  11. 0. Introduction • Approach to repetitive algorithms • Iteration (loop) • while 루프, for 루프 • Recursion (function call to itself) • A recursive call is a function call in which the called function is the same as the one making the call. • In other words, recursion occurs when a function calls itself! • Suitable for problem breaking-down • Divide-and-conquer • Many algorithms are drastically simplified by recursion Data Structure

  12. 1. Factorial – A Case Study • Iterative definition of factorial • Recursive definition of factorial • Recursive Definition • A의 정의 파트에 다시 A를 사용하는 정의 Data Structure

  13. 1. Factorial – A Case Study • Factorial of 3 (by recursion) • Factorial(3) = 3 * factorial(2) = 3 * 2 * factorial(1) = 3 * 2 * 1 * factorial(0) = 3 * 2 * 1 * 1 = 6 Data Structure

  14. 1. Factorial – A Case Study • n! = n * (n-1) * (n-2) * ... * 1   (단, 1! = 0! = 1) Data Structure

  15. 1. Factorial – A Case Study Data Structure

  16. 1. Factorial – A Case Study • Iterative Algorithm of Factorial Data Structure

  17. 1. Factorial – A Case Study • Recursive Algorithm of Factorial Data Structure

  18. 1. Factorial – A Case Study • Trace of Recursion • [소스코드] • int recursiveFactorial(int n) { if (n = = 1) return 1; else                return(n * recursiveFactorial(n-1)); } Data Structure

  19. 1. Factorial – A Case Study • Function call is implemented using “Activation Record” Ex) recursiveFactorial(1) calls recursiveFactorial(0) void recursiveFactorial(1) { … recursiveFactorial(0); … } void recursiveFactorial(0) { … … … } Local variables of recursiveFac(0) Activation Record for recursiveFactorial(0) Homeward Address parameter of recursiveFac(0) Local variables of recursiveFac(1) Activation Record for recursiveFactorial(1) Homeward Address parameter of recursiveFac(1) Activation Record for recursiveFactorial(2) Activation Record for recursiveFactorial(3) Data Structure

  20. 1. Factorial – A Case Study • Activation Records for Recursive Call • [소스코드] • int Factorial(int n) { if (n = = 1) return 1; else                return(n * Factorial(n-1)); } Data Structure

  21. 2. Designing Recursive Algorithm • Every recursive algorithm has two elements • Solve a primitive problem  non-recursive solution • Base case • Reduce the size of problem  recursion • General case Data Structure

  22. 2. Designing Recursive Algorithm • Rules for designing a recursive algorithm 1. Determine base case • Non-recursive solution of primitive case such as n = 0, 1 2. Determine general case • Break down the problem into sub-problems which are the same, but smaller than original • Assume sub-problems are already solved Ex) To calculate factorial(n), assume factorial(n-1), factorial(n-2), …, factorial(0) are solved 3. Combine base and general cases Data Structure

  23. 2. Designing Recursive Algorithm • Recursion is effective for • Problems that are naturally recursive • Binary search (chap. 13) • Algorithms that use a data structure naturally recursive • Tree (chap, 6) • Disadvantege of recursion • Function call overhead • Time • Stack memory Data Structure

  24. 2. Designing Recursive Algorithm • You should not use recursion if the answer to any of the following question is NO: • 1. Is the algorithm or data structure naturally suited to recursion? • 2. Is the recursive solution shorter and more understandable? • 3. Does the recursive solution run within acceptable time and space limits? • 4. Is the recursive solution’s efficiency logarithmic? Data Structure

  25. 2. Designing Recursive Algorithm • 문제 정의: 문자열뒤집기 • 길이 4인 문자열 “Good”가 주어지면 결과로서 “dooG”를 얻음 • 재귀적 접근방법 • 길이 n의 문제를 길이 n-1의 문제로 환원 • 주어진 문자열의 길이를 하나 줄이기 위하여 하나의 문자를 떼어냄 • 어떤 문자를 떼어내는가? void Reverse(char S[ ], int Size){ if (Size = = 0) return;                        //  호출함수로 되돌아감 else {   printf("%c", S[Size-1]);       // 마지막 문자를 쓰기 Reverse(S, Size-1);            // 재귀호출 } } 재귀호출에서 되돌아가는 과정에서는 아무런 작업을 하지 않음 교재 50~52 의 “Reverse Keyboard Input” 대신에 본 자료의 “문자열 뒤집기”내용을익힐것 Data Structure

  26. 2. Designing Recursive Algorithm • 문자열 뒤집기 A void Reverse(char S[ ], int First, int Last) { if (First > Last) return;          else { printf("%c", S[First]);  Reverse(S, First+1, Last); } } 호출방법:Reverse(“Good”, 0, 3); B void Reverse(char S[ ], int First, int Last) { if (First > Last) return;          else { Reverse(S, First+1, Last); printf("%c", S[First]);  } } A와 B중 어느 것이 맞을까? Data Structure

  27. 2. Designing Recursive Algorithm • 문자열 뒤집기 void Reverse(char S[ ], int First, int Last) { if (First > Last) return;          else { Reverse(S, First+1, Last); printf("%c", S[First]);  } } Data Structure

  28. 2. Designing Recursive Algorithm • 문자열 뒤집기 void Reverse(char S[ ], int First, int Last) { if (First > Last) return;          else { Reverse(S, First+1, Last); printf("%c", S[First]);  } } 1. Is the algorithm or data structure naturally suited to recursion? NO입력내용이 일렬로 배열된형태는 근본적으로 재귀적 구조가 아니다. 2. Is the recursive solution shorter and more understandable? YES or NO 3. Does the recursive solution run within acceptable time and space limits? NO O(n) 4. Is the recursive solution’s efficiency logarithmic? NO O(n) Data Structure

  29. 3. Recursive Examples • Greatest Common Divisor (최대공약수) • GCD’s Recursive Definition (Euclidian Algorithm) • Recursive algorithm • Implementation • Page 53~54 gcd(a, b) = a if b = 0 = b if a = 0 = gcd(b, a % b) otherwise int gcd (int a, int b) { if (b == 0) // Base Case return a; if (a == 0) // Base Case return b; return gcd (b, a % b); // General Case } Data Structure

  30. 3. Recursive Examples • FibonacciNumbers • Each number is the sum of previous two numbers 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … • Recursive Definition • Recursive Algorithm • Implementation • Page 56~57 Fibonacci(n) = 0 if n = 0 = 1 if n = 1 = Fibonacci(n-1) + Fibonacci(n-2) long fib (long num) { // Base Case if (num == 0 || num == 1) return num; // General Case return (fib (num - 1) + fib (num - 2)); } Data Structure

  31. 3. Recursive Examples • FibonacciNumbers Data Structure

  32. 3. Recursive Examples • FibonacciNumbers • # of function calls to calculate Fibonacci numbers Data Structure

  33. 3. Recursive Examples • Prefix to Postfix Conversion • Arithmetic expressions • Infix: operator comes between operands • Ex) A+B • Prefix: operator comes before operands • Ex) +AB • Postfix: operator comes after operands • Ex) AB+ • Prefix to postfix conversion • +AB  AB+ • -+*ABC/EF  ? + A B Data Structure

  34. 3. Recursive Examples • Prefix to Postfix Conversion • Parse Tree Data Structure

  35. 3. Recursive Examples • Prefix to Postfix Conversion • How to design algorithm? • Note: the algorithm will parse the given ‘Prefix’ from left to right 2 0 - +*ABC /EF - AB*C+ EF/ AB*C+ EF/ - 1 3 General Strategy 0. Identify Operator 1. Convert left operand 2. Convert right operand 3. Concatenate converted operands and operator Data Structure

  36. 3. Recursive Examples Base Case 0. Find just one operand 1. return it ! • Prefix to Postfix Conversion • How to design algorithm? 2 0 - +*ABC /EF - AB*C+ EF/ AB*C+ EF/ - 1 3 2 0 + *AB C + AB* C AB* C + 1 3 2 2 0 0 * A B * A B AB * / E F / E F EF / 1 1 3 3 Data Structure

  37. 3. Recursive Examples • Prefix to Postfix Conversion • Implementation (Program 2-3) #include <stdio.h> #include <string.h> #define OPERATORS "+-*/“ void preToPostFix (char* preFixIn, char* exprOut); int findExprLen (char* exprIn); int main (void) { char preFixExpr[256] = "-+*ABC/EF"; char postFixExpr[256] = ""; printf("Begin prefix to postfix conversion\n\n"); preToPostFix(preFixExpr, postFixExpr); printf("Prefix expr: %-s\n", preFixExpr); printf("Postfix expr: %-s\n", postFixExpr); printf("\nEnd prefix to postfix conversion\n"); return 0; } Data Structure

  38. 3. Recursive Examples • Prefix to Postfix Conversion • Implementation (Program 2-3) void preToPostFix (char* preFixIn, char* postFix) { char operator [2]; char postFix1[256]; char postFix2[256]; char temp [256]; int lenPreFix; if (strlen(preFixIn) == 1) { *postFix = *preFixIn; *(postFix + 1) = '\0'; return; } *operator = *preFixIn; *(operator + 1) = ‘\0’; lenPreFix = findExprLen (preFixIn + 1); strncpy (temp, preFixIn + 1, lenPreFix); *(temp + lenPreFix) = '\0'; preToPostFix (temp, postFix1); strcpy (temp, preFixIn + 1 + lenPreFix); preToPostFix (temp, postFix2); strcpy (postFix, postFix1); strcat (postFix, postFix2); strcat (postFix, operator); return; } Data Structure

  39. 3. Recursive Examples • Prefix to Postfix Conversion "-+*ABC/EF" "" "" "+*ABC" preToPostFix (char* preFixIn, char* postFix) preToPostFix (char* preFixIn, char* postFix) operator ="+" operator ="-" 1) "" "+*ABC" "" "*AB" preToPostFix (temp, postFix1) preToPostFix (temp, postFix2) preToPostFix (temp, postFix1) preToPostFix (temp, postFix2) "/EF" "" "C" "" 3) 2) "AB*C+" "AB*" strcpy (postFix, postFix1); strcat (postFix, postFix2); strcat (postFix, operator); strcpy (postFix, postFix1); strcat (postFix, postFix2); strcat (postFix, operator); "EF/" "C" "-" "+" Data Structure

  40. 3. Recursive Examples • Prefix to Postfix Conversion "" "*AB" "" "/EF" preToPostFix (char* preFixIn, char* postFix) preToPostFix (char* preFixIn, char* postFix) operator ="/" operator ="*" "" "A" "" "E" preToPostFix (temp, postFix1) preToPostFix (temp, postFix2) preToPostFix (temp, postFix1) preToPostFix (temp, postFix2) "B" "" "F" "" "A" "E" strcpy (postFix, postFix1); strcat (postFix, postFix2); strcat (postFix, operator); strcpy (postFix, postFix1); strcat (postFix, postFix2); strcat (postFix, operator); "B" "F" "*" "/" Data Structure

  41. 3. Recursive Examples • 첫번째 Expression의 길이 알아오기 (재귀적) • Implementation int findExprLen (char* exprIn) { int len1; int len2; if (strcspn (exprIn, OPERATORS) == 0) { //expIn’s first character is operator len1 = findExprLen(exprIn + 1); len2 = findExprLen(exprIn + 1 + len1); } else len1 = len2 = 0; return len1 + len2 + 1; } 3 1 "+*ABC/EF" size_t strcspn(const char *s1, const char *s2); s1 문자열에서 s2 문자열에 포함된 임의의 문자와 매칭되는 인덱스를 리턴함 1 3 1 Data Structure

  42. 3. Recursive Examples • 첫번째 Expression의 길이 알아오기 (재귀적) 0 0 1 0 0 1 0 0 1 Data Structure

  43. 3. Recursive Examples • Towers of Hanoi • Input • Three towers (source, destination, auxiliary) • n disks of different diameters placed on source tower in decreasing diameter • Problem • Move all disks from source tower to destination tower • Rules • Only one disk can be moved at any time • No disk can be placed on top of a disk with a smaller diameter Data Structure

  44. 3. Recursive Examples • Towers of Hanoi • Algorithm design • Base case: only one disk to move • Just move it • General case: # of disk > 1  How to break down the problem ? Data Structure

  45. 3. Recursive Examples • Towers of Hanoi • Moving 2 disks (from source to destination) • 1. Move one disk from source to auxiliary • 2. Move one disk from source to destination • 3. Move one disk from auxiliary to destination Data Structure

  46. 3. Recursive Examples • Towers of Hanoi • Moving 3 disks (from source to destination) • 1. Move two disk from source to auxiliary • 2. Move one disk from source to destination • 3. Move two disk from auxiliary to destination 1 2 3 Data Structure

  47. 3. Recursive Examples • Towers of Hanoi • Moving n disks (from source to destination) • 1. move n -1 disks from source to auxiliary • 2. move 1 disk from source to destination • 3. move n -1 disks from auxiliary to destination void towers (int n, char source, char dest, char auxiliary) { static int step = 0; printf("Towers (%d, %c, %c, %c)\n", n, source, dest, auxiliary); if (n == 1) printf("\t\t\tStep %3d: Move from %c to %c\n", ++step, source, dest); else { towers(n - 1, source, auxiliary, dest); printf("\t\t\tStep %3d: Move from %c to %c\n", ++step, source, dest); towers(n - 1, auxiliary, dest, source); } } Data Structure

  48. 3. Recursive Examples • Towers of Hanoi • Moving 3 disks [Output] Towers(3,A,C,B) Towers(2,A,B,C) Towers(1,A,C,B) Move from A to C Move from A to B Towers(1,C,B,A) Move from C to B Move from A to C Towers(2,B,C,A) Towers(1,B,A,C) Move from B to A Move from B to C Towers(1,A,C,B) Move from A to C Data Structure

  49. 3. Recursive Examples • Towers of Hanoi • Moving 3 disks [Output] Towers(3,A,C,B) Towers(2,A,B,C) Towers(1,A,C,B) Move from A to C Move from A to B Towers(1,C,B,A) Move from C to B Move from A to C Towers(2,B,C,A) Towers(1,B,A,C) Move from B to A Move from B to C Towers(1,A,C,B) Move from A to C Data Structure

  50. 4. 재귀 호출의 효율성 • 재귀 호출시 Activation Record의 비효율 • 공간적 비효율(저장 공간) • 시간적 비효율(저장, 복원에 걸리는 시간) • 가능하다면 반복문으로 대치하는 것이 유리 int Factorial(int n) {                       int product = 1; for (int i = 1; i <= n; i++) product *= i; return product; }        void Reverse(char S[ ], int Size)  { while (Size > 0){ printf("%c", S[Size-1]);         --Size;                             } }     Data Structure

More Related