180 likes | 278 Views
CSE 1342 Programming Concepts. Recursion. Overview of Recursion. Recursion is present when a function is defined in terms of itself. The factorial of an integer can be expressed using a recursive definition. For example, 5 factorial (5!) may be expressed as:
E N D
CSE 1342Programming Concepts Recursion
Overview of Recursion • Recursion is present when a function is defined in terms of itself. • The factorial of an integer can be expressed using a recursive definition. For example, 5 factorial (5!) may be expressed as: 5! = 5 * 4 * 3 * 2 * 1 However, a more concise definition involving recursion would be 5! = 5 * 4! Now, in order to find the definition of 5! We must first find the definition of 4!, then 3!, then 2! And finally 1!.
Overview of Recursion 5! = 5 * 4! 4! = 4 * 3! 3! = 3 * 2! 2! = 2 * 1! 1! = 1 (basis case or stopping state) • A more generic recursive factorial definition would be: N! = N * (N-1)! • This assumes that N >= 0 and that the factorial of 0 is 1 and the factorial of 1 is also 1 (a non-recursive definition).
Factorial Example • Converting the mathematical definition to an equivalent software algorithm we have ... unsigned int factorial(unsigned long number) { if (number <= 1) return 1; // basis case or stopping state else return number * factorial(number - 1); // direct recursive call } • Notice how the last statement conforms to the expression N * (N-1)!
Overview of Recursion • As discussed earlier, control structures may be categorized as either sequential structures, selection structures or repetition structures. • Recursion is a technique by which to achieve repetition. • Iterative loops such as while, do while and for are the other technique. • Any algorithm that can be expressed iteratively can also be expressed recursively, and visa versa.
Overview of Recursion • In many cases an algorithm expressed recursively is more concise than when expressed iteratively. • In general, recursive algorithms run slower and require more memory than do iterative algorithms. • This often leads to a trade-off between efficiency and simplicity of expression. • There are two types of recursion • Direct recursion is when a function contains a call to itself within its own body. • The factorial function is an example of direct recursion.
Overview of Recursion • Indirect recursion is when a function calls a second function which in turn calls the first function. void g( ) { f ( ); // indirect recursive call } void f ( ) { g ( ); } void main ( ) { f ( ); }
Stacks and Function Calls • A stack is a last-in-first-out data structure used by program translators in the implementation of function calls, both recursive and non-recursive. • A stack is is operated on by two functions - push and pop. • Push adds a new data element to the top of the stack. • Pop removes an existing data element from the top of the stack. • Whenever a program translator encounters a function call it generates the code to push a return address and any function arguments that need to be passed to the called function onto the stack.
Stacks and Function Calls • Whenever a program translator encounters a return statement it generates the code to pop a return address from the top of the stack (and into the instruction pointer) as well as any parameters that might have been previously pushed. • The pops must be in the opposite order of the corresponding pushes. • In this way a program can find its way back from any number of nested function calls. • Understanding the relationship between stacks and function calls can help in walking through complex recursive algorithms.
Non-Recursive Factorial Example unsigned int factorial (unsigned int x) { unsigned int fact=1; while(x>1) { fact=fact*x; x--; } return fact; }
Recursive Factorial Example unsigned int factorial(unsigned long number) { if (number <= 1) return 1; // basis case or stopping state else return number * factorial(number - 1); }
NON-RECURSIVE PALINDROME DETECTION FUNCTION bool pdrome(char a[ ], int lb, int ub) { bool pflag = true; while(lb < ub && pflag) { if(a[lb] != a[ub]) //string is not a palindrome pflag = false; else { //string is a palindrome so far lb++; ub--; } } return pflag; }
RECURSIVE PALINDROME DETECTION FUNCTION bool recPdrome(char a[ ], int lb, int ub) { if(lb >= ub) //string is a palindrome return true; else if(a[lb] != a[ub]) //string not a palindrome return false; else //string is palindrome so far return recPdrome(a, lb+1, ub-1); }
NON-RECURSIVE BINARY SEARCH int search(int a[], int lb, int ub, int value) { //Non-recursive binary search routine int half, found = 0; while (lb <= ub && found == 0) { half = (lb+ub) / 2; if(a[half] == value) found = 1; else if(a[half] > value) ub = half-1; //calculate new upper bound else lb = half+1; //calculate new lower bound } (found) ? return half : return -1; }
RECURSIVE BINARY SEARCH int recSearch(int a[], int lb, int ub, int value) { //Recursive binary search routine int half; if(lb > ub) return -1; //value is not in the array half = (lb+ub) / 2; if(a[half] == value) //value is in the array return half; //return value's location else if(a[half] > value) return recSearch(a, lb, half-1, value); //search lower half of array else return recSearch(a, half+1, ub, value); //search upper half of array }
TOWERS OF HANOI DRIVER void towers(int, int, int, int); main() { int nDisks; cout << “Enter the starting number of disks: “; cin >> nDisks; towers (nDisks, 1, 3, 2); return 0; }
TOWERS OF HANOI void towers(int disks, int start, int end, int temp) { if (disks == 1) { cout << start << “ TO ” << end << endl; return; } // move disks – 1 disks from start to temp towers (disks – 1, start, temp, end); // move last disk from start to end cout << start << “” << end << endl; // move disks – 1 disks from temp to end towers (disks – 1, temp, end, start); }