Data Structures Algorithms Lecture 2 Data Structures Algorithms

  • Slides: 79
Download presentation
Data Structures & Algorithms Lecture # 2

Data Structures & Algorithms Lecture # 2

Data Structures & Algorithms Abstract Data Type(ADT): We have looked at two different implementations

Data Structures & Algorithms Abstract Data Type(ADT): We have looked at two different implementations of the List data structures: § § Using arrays Singly linked list The interface to the List stayed the same, i. e. , add(), get(), next(), start(), remove() etc. The list is thus an abstract data type; we use it without being concerned with how it is implemented.

Data Structures & Algorithms Abstract Data Types (ADTs): An abstract data type (ADT) is

Data Structures & Algorithms Abstract Data Types (ADTs): An abstract data type (ADT) is a set of objects together with a set of operations. Abstract data types are mathematical abstractions; where in an ADT’s definition is there any mention of how the set of operations is implemented. Objects such as lists, Stack, Queue, Sets, and Graphs, along with their operations, can be viewed as ADTs, just as integers, reals, and booleans are data types. Integers, reals, and booleans have operations associated with them, and so do ADTs. E. g. List Operations are search, delete, update, copy, and sort etc. The C++ class allows for the implementation of ADTs. • What we care about is the methods that are available for use with the List ADT. • We will follow this theme when we develop other ADT. • We will publish the interface and keep the freedom to change the implementation of ADT without effecting users of the ADT.

Data Structures & Algorithms Stack: § Stacks in real life: stack of books, stack

Data Structures & Algorithms Stack: § Stacks in real life: stack of books, stack of plates, stack of Towels etc. § Add new items at the top § Remove an item from the top § Stack data structure similar to real life: collection of elements arranged in a linear order. § Can only access element at the top § Push(X) – insert X as the top element of the stack. § Pop() – remove the top element of the stack and return it. § Top() – return the top element without removing it from the stack.

Data Structures & Algorithms top top top 7 5 2 1 pop() 1 7

Data Structures & Algorithms top top top 7 5 2 1 pop() 1 7 7 5 2 2 5 2 push(2) push(5) push(7) push(1) 21 7 5 2 push(21) top 7 5 2 21 pop() top 5 2 7 pop() 2 top 5 pop()

Data Structures & Algorithms § The last element to go into the stack is

Data Structures & Algorithms § The last element to go into the stack is the first to come out: LIFO – Last In First Out. § Throw Stack. Empty exception: advanced C++ concept. § Stack Using Array: top 1 7 5 2 2 5 7 1 0 1 2 3 top = 3 4

Data Structures & Algorithms § What happens if we call pop() and there is

Data Structures & Algorithms § What happens if we call pop() and there is no element? § Have Is. Empty() boolean function that returns true if stack is empty, false otherwise. § In case of an array, it is possible that the array may “fill-up” if we push enough elements. § Have a boolean function Is. Full() which returns true is stack (array) is full, false otherwise. § We would call this function before calling push(x). § Worst case for insertion and deletion from an array when insert and delete from the beginning: shift elements to the left. § Best case for insert and delete is at the end of the array – no need to shift any elements. § Implement push() and pop() by inserting and deleting at the end of an array.

Data Structures & Algorithms PUSH(STACK, TOP, MAXSTK, ITEM) 1. [Stack Already Filled] if TOP=MAXSTK,

Data Structures & Algorithms PUSH(STACK, TOP, MAXSTK, ITEM) 1. [Stack Already Filled] if TOP=MAXSTK, then “Overflow” Exit. 2. Set TOP=TOP+1 3. STACK[TOP]=ITEM 4. Exit. POP(STACK, TOP, ITEM) 1. [STACK has an item to be removed? ? ] if TOP=Null, then “Underflow” exit. 2. Set ITEM= STACK[TOP] 3. Set TOP=TOP-1 4. Exit

Data Structures & Algorithms int pop() { return A[current-]; } void push(int x) {

Data Structures & Algorithms int pop() { return A[current-]; } void push(int x) { A[++current] = x; } int top() { return A[current]; } int Is. Empty() { return ( current == -1 ); } int Is. Full() { return ( current == size 1); } A quick examination shows that all five operations take constant time.

Data Structures & Algorithms Stack Using Linked List: § We can avoid the size

Data Structures & Algorithms Stack Using Linked List: § We can avoid the size limitation of a stack implemented with an array by using a linked list to hold the stack elements. § As with array, however, we need to decide where to insert elements in the list and where to delete them so that push and pop will run the fastest. § For a singly-linked list, insert at start or end takes constant time using the head and current pointers respectively. § Removing an element at the start is constant time but removal at the end required traversing the list to the node one before the last.

Data Structures & Algorithms § Make sense to place stack elements at the start

Data Structures & Algorithms § Make sense to place stack elements at the start of the list because insert and removal are constant time. § No need for the current pointer; head is enough. head top 1 7 5 2

Data Structures & Algorithms int pop() { int x = head->get(); Node* p =

Data Structures & Algorithms int pop() { int x = head->get(); Node* p = head; head = head->get. Next(); delete p; return x; } head top 7 5 2 1 7 5 2

Data Structures & Algorithms void push(int x) { Node* new. Node = new Node();

Data Structures & Algorithms void push(int x) { Node* new. Node = new Node(); new. Node->set(x); new. Node->set. Next(head); head = new. Node; } top head 9 7 5 2 7 new. Node push(9) 9 5 2

Data Structures & Algorithms int top() { return head->get(); } int Is. Empty() {

Data Structures & Algorithms int top() { return head->get(); } int Is. Empty() { return ( head == NULL ); } All four operations take constant time.

Data Structures & Algorithms Stack: Array or List § Since both implementations support stack

Data Structures & Algorithms Stack: Array or List § Since both implementations support stack operations in constant time, any reason to choose one over the other? § Allocating and deallocating memory for list nodes does take more time than pre-allocated array. § List uses only as much memory as required by the nodes; array requires allocation ahead of time. § List pointers (head, next) require extra memory. § Array has an upper limit; List is limited by dynamic memory allocation.

Data Structures & Algorithms Use of Stack: § Example of use: prefix, infix, postfix

Data Structures & Algorithms Use of Stack: § Example of use: prefix, infix, postfix expressions. § Consider the expression A+B: we think of applying the operator “+” to the operands A and B. § Writing the sum as A+B is called the infix form of the expression. § Two other ways of writing the expression are: +AB prefix AB+ postfix § The prefixes “pre” and “post” refer to the position of the operator with respect to the two operands.

Data Structures & Algorithms § Consider the infix expression A+B*C § We “know” that

Data Structures & Algorithms § Consider the infix expression A+B*C § We “know” that multiplication is done before addition. § The expression is interpreted as A+(B*C) § Multiplication has precedence over addition.

Data Structures & Algorithms § The five binary operators are: addition, subtraction, multiplication, division

Data Structures & Algorithms § The five binary operators are: addition, subtraction, multiplication, division and exponentiation. § The order of precedence is (highest to lowest) § Exponentiation § Multiplication/division *, / § Addition/subtraction +, § For operators of same precedence, the left-to-right rule applies: A+B+C means (A+B)+C. § For exponentiation, the right-to-left rule applies A B C means A ( B C )

Data Structures & Algorithms Infix Postfix A+B AB+ 12 + 60 – 23 12

Data Structures & Algorithms Infix Postfix A+B AB+ 12 + 60 – 23 12 60 + 23 – (A + B)*(C – D ) AB+CD–* A B * C – D + E/F A B C*D – E F/+ Note that the postfix form an expression does not require parenthesis. § Consider ‘ 4+3*5’ and ‘(4+3)*5’. The parenthesis are not needed in the first but they are necessary in the second. § The postfix forms are: 4+3*5 435*+ (4+3)*5 43+5*

Data Structures & Algorithms 1) Add “)” at the end of P. 2) Scan

Data Structures & Algorithms 1) Add “)” at the end of P. 2) Scan P from left to right and repeat steps 3 & 4 for each element of P until “)” is encounter. 3) If an operand is encounter put it on to STACK. 4) If an operator is encounter then: a) Remove the two top element of STACK e. g. a, b, + b) Evaluate the a+b and put the result back on STACK. 5. Set Value equal to the top element on STACK. 6. Exit.

Data Structures & Algorithms Stack s; while( not end of input ) { e

Data Structures & Algorithms Stack s; while( not end of input ) { e = get next element of input if( e is an operand ) s. push( e ); else { op 2 = s. pop(); op 1 = s. pop(); value = result of applying operator ‘e’ to op 1 and op 2; s. push( value ); } } finalresult = s. pop();

Data Structures & Algorithms Evaluate 6 2 3 + - 3 8 2 /

Data Structures & Algorithms Evaluate 6 2 3 + - 3 8 2 / + * 2 3 +) Input op 1 op 2 value 6 6 2 6, 2 3 6, 2, 3 stack + 2 3 5 6, 5 - 6 5 1 1 3 6 5 1 1, 3 8 6 5 1 1, 3, 8 2 6 5 1 1, 3, 8, 2 / 8 2 4 1, 3, 4 + 3 4 7 1, 7 * 1 7 7 7 2 1 7 7 7, 2 7 2 49 49 3 7 2 49 49, 3 + 49 3 52 52

Data Structures & Algorithms 1) Push “(” onto Stack and Add “)” to the

Data Structures & Algorithms 1) Push “(” onto Stack and Add “)” to the end of Q. 2) Scan Q from left to right and repeat steps 3 & 6 for each element of Q until STACK empty. 3) If an operand is encounter , add it to P. 4) If left parenthesis is encounter , push it onto STACK 5) If an operator is encounter then: a) Repeatedly pop from STACK and add to P each operator which has same or higher precedence than operator b) Add operator to STACK. end if 6) If a right parenthesis is encounter then: a) Repeatedly pop from STACK and add it to P each operator until a left parenthesis is encounter. Do not add a left parenthesis to P. b) Remove left parenthesis. Do not add the left parenthesis to P. end if end of loop 7) Exit.

Data Structures & Algorithms 1. Stack s; 2. While( not end of input )

Data Structures & Algorithms 1. Stack s; 2. While( not end of input ) { 3. c = next input character; 4. if( c is an operand ) 5. add c to postfix string; 6. else { 7. while( !s. empty() && prcd(s. top(), c) ){ 8. op = s. pop(); 9. add op to the postfix string; 10. } 11. s. push( c ); 12. } 13. while( !s. empty() ) { 14. op = s. pop(); 15. add op to postfix string; 16. } prcd(‘*’, ’+’) is TRUE prcd(‘+’, ’*’) is FALSE

Data Structures & Algorithms • Example: A + B * C symbol postfix A

Data Structures & Algorithms • Example: A + B * C symbol postfix A A + A B AB * AB C ABC * + stack + + +* +* +

Data Structures & Algorithms Function Call: Stacks play a key role in implementation of

Data Structures & Algorithms Function Call: Stacks play a key role in implementation of function call in programing languages. In C++, for example the call stack is used to pass function arguments and receive and return values. The call stack is also used for local variables.

Data Structures & Algorithms In GCC, a popular C/C++ compiler on Intel platform, stack

Data Structures & Algorithms In GCC, a popular C/C++ compiler on Intel platform, stack entries are: n*4(%esp) 8(%esp) 4(%esp) last argument ………. second argument first argument return address top

Data Structures & Algorithms Example: consider the function: int avg (int a, int b)

Data Structures & Algorithms Example: consider the function: int avg (int a, int b) { return (a + b) / 2; } # Stack layout on entry: # # 8(%esp) b # 4(%esp) a # (%esp) return address . globl _avg: movl 4(%esp), %eax addl 8(%esp), %eax # Add the args sarl $1, %eax # Divide by 2 ret # Return value is in %eax

Data Structures & Algorithms Memory Organization: § When a program (. exe) is run,

Data Structures & Algorithms Memory Organization: § When a program (. exe) is run, it is loaded in memory. It becomes a process. § The process is given a block of memory. § [Control-Alt-DEL] Process 1 (browser) Process 3 (word) Process 4 (excel) Process 2 (dev-c++) Windows OS

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms Process 1 (browser) Code Process 3 (word) Static data Process

Data Structures & Algorithms Process 1 (browser) Code Process 3 (word) Static data Process 4 (excel) Stack Process 2 (dev-c++) Windows OS Heap

Data Structures & Algorithms Stack Layout during a call: Here is stack layout when

Data Structures & Algorithms Stack Layout during a call: Here is stack layout when function F calls function G: Parameters(F) sp Parameters(F) Local variables(F) Return address(F) Parameters(G) sp Local variables(G) sp At point of call Return address(G) During execution of G After call

Data Structures & Algorithms § Stack is a useful tool for implementing recursive calls.

Data Structures & Algorithms § Stack is a useful tool for implementing recursive calls. § Reversing string Push the characters of string one by one on to the stack and then pop out. § Balancing Symbols (braces, brackets, parenthesis) Make an empty stack, read characters until end of file. If the character is an opening symbol, push it on to the stack. If it is a closing symbol, then if the stack is empty report an error, otherwise pop the stack. If the popped symbol is not the corresponding opening symbol, report an error. At the end of file if the stack is not empty then report an error

Data Structures & Algorithms Queue: § A stack is LIFO (Last-In First Out) structure.

Data Structures & Algorithms Queue: § A stack is LIFO (Last-In First Out) structure. § In contrast, a queue is a FIFO (First-In First-Out ) structure. § A queue is a linear structure for which items can be only inserted at one end and removed at another end i. e. FCFS. Real Life Examples: paying utility bills, passenger waiting at station etc Queue Operations: Enqueue(X): place X at the rear of the queue. Dequeue(): remove the front element and return it. Front(): return front element without removing it. Is. Empty(): return TRUE if queue is empty, FALSE otherwise

Data Structures & Algorithms Queue using Array: § If we use an array to

Data Structures & Algorithms Queue using Array: § If we use an array to hold queue elements, both insertions and removal at the front (start) of the array are expensive. § This is because we may have to shift up to “n” elements. § For the stack, we needed only one end; for queue we need both. § To get around this, we will not shift upon removal of an element.

Data Structures & Algorithms front rear 1 7 5 2 1 0 7 1

Data Structures & Algorithms front rear 1 7 5 2 1 0 7 1 1 7 2 2 3 4 front rear 0 3 Enqueue(6) front 5 5 6 7 rear 5 2 6 1 0 7 1 front 0 5 2 6 2 3 4 rear 4

Data Structures & Algorithms Enqueue(8) front 1 rear 7 5 2 6 8 1

Data Structures & Algorithms Enqueue(8) front 1 rear 7 5 2 6 8 1 0 1 5 2 6 8 2 3 4 5 front 0 Dequeue() front 7 7 6 7 rear 5 2 6 7 8 0 1 front 1 5 2 6 8 2 3 4 5 rear 5

Data Structures & Algorithms Dequeue() front 5 rear 2 6 8 0 Enqueue(9) Enqueue(12)

Data Structures & Algorithms Dequeue() front 5 rear 2 6 8 0 Enqueue(9) Enqueue(12) front 5 1 5 2 6 8 2 3 4 5 6 7 front 2 rear 5 rear 2 6 8 9 12 0 Enqueue(21) ? ? 1 front 2 5 2 6 8 9 12 2 3 4 5 6 7 rear 7

Data Structures & Algorithms § We have inserts and removal running in constant time

Data Structures & Algorithms § We have inserts and removal running in constant time but we created a new problem. § Cannot insert new elements even though there are two places available at the start of the array. § Solution: allow the queue to “wrap around”. § Basic idea is to picture the array as a circular array. 0 front 5 rear 2 6 8 7 9 12 6 1 12 5 9 2 8 5 6 4 2 3 front 2 rear 7

Data Structures & Algorithms Enqueue(21) front 5 rear 2 6 8 7 0 21

Data Structures & Algorithms Enqueue(21) front 5 rear 2 6 8 7 0 21 1 12 5 9 2 9 12 21 6 8 5 void enqueue(int x) { rear = (rear+1); array[rear] = x; no. Elements = no. Elements+1; } 6 4 2 3 front 2 size 8 rear 0 no. Elements 7

Data Structures & Algorithms Enqueue(7) front 5 rear 2 6 8 7 9 12

Data Structures & Algorithms Enqueue(7) front 5 rear 2 6 8 7 9 12 21 7 6 int is. Full() { return no. Elements == size; } int is. Empty() { return no. Elements == 0; } 0 21 1 7 12 5 9 2 8 5 6 4 2 3 front 2 size 8 rear 1 no. Elements 8

Data Structures & Algorithms Dequeue() 0 front 6 rear 8 7 9 12 21

Data Structures & Algorithms Dequeue() 0 front 6 rear 8 7 9 12 21 7 6 int dequeue() { int x = array[front]; front = (front+1); no. Elements = no. Elements-1; return x; } 1 21 7 2 12 9 8 5 3 6 4 front 4 size 8 rear 1 no. Elements 6

Data Structures & Algorithms INSERTION 1. [check for overflow] if R>=N (then write overflow

Data Structures & Algorithms INSERTION 1. [check for overflow] if R>=N (then write overflow and exit) 2. [increment Rear by 1] If (R==Null) then R=0 else R=R+1 3. [Insert new item ‘x’ at R] Q[R]=x 4. [is front pointer is properly set] if F=Null then F=0 5. exit DELETION 1. [Check for underflow ] if F=R=Null then (write underflow and exit) 2. [delete item from queue] temp=Q[F] 3. [Set front and rear pointers] if F=R the set F=R=Null else F=F+1 4. Exit

Data Structures & Algorithms CQueue INSERTION 1. [check for overflow] if (F=0 & R=N)

Data Structures & Algorithms CQueue INSERTION 1. [check for overflow] if (F=0 & R=N) OR ( F=R+1) (then write overflow and exit) 2. [increment Rear by 1] if F=R=Null then F=R=0 else if (R=N) then R=0 else R=R+1 3. [Insert new item ‘x’ at R] Q[R]=x 5. exit CQueue DELETION 1. [check for underflow] if (F=R=Null) (then write underflow and exit) 2. [delete item] temp=Q[F] 3. [Set F and R pointer] if(F=R) then F=R= Null else if (F=N) then F=0 else F=F+1 4. exit

Data Structures & Algorithms Implementing Queue using Linked List: § Insert works in constant

Data Structures & Algorithms Implementing Queue using Linked List: § Insert works in constant time for either end of a linked list. § Remove works in constant time only. § Seems best that head of the linked list be the front of the queue so that all removes will be from the front. § Inserts will be at the end of the list. front 1 7 rear 5 2 rear front 1 7 5 2

Data Structures & Algorithms Dequeue() front 7 5 rear front rear 1 2 7

Data Structures & Algorithms Dequeue() front 7 5 rear front rear 1 2 7 5 2 Enqueue(9) front 7 rear 5 2 9 rear front 7 5 2 9

Data Structures & Algorithms int Dequeue() { int x = front->get(); Node* p =

Data Structures & Algorithms int Dequeue() { int x = front->get(); Node* p = front; front = front->get. Next(); delete p; return x; } int front() { return front->get(); } void Enqueue(int x) { Node* new. Node = new Node(); new. Node->set(x); new. Node->set. Next(NULL); rear->set. Next(new. Node); rear = new. Node; } int Is. Empty() { return ( front == NULL ); }

Data Structures & Algorithms Priority Queue: A priority queue is a collection of elements

Data Structures & Algorithms Priority Queue: A priority queue is a collection of elements such that each element has been assigned a priority and such that the order in which elements are deleted and inserted using the following rules: § An element of higher priority is processed before any element of lower priority § Two elements of the same priority are processed on the FCFS basis. e. g. time sharing system, programs of higher priority are processed first.

Data Structures & Algorithms Linked List Representation of Priority Queue: § Each node in

Data Structures & Algorithms Linked List Representation of Priority Queue: § Each node in the list will contain three parts: info, prn, next. § A node X precede a node Y in the list (1) when X has higher priority than Y (2) when both have the same priority but X added first. INFO PRN Next

Data Structures & Algorithms Start AAA 1 BBB 2 CCC 2 HHH 2 DDD

Data Structures & Algorithms Start AAA 1 BBB 2 CCC 2 HHH 2 DDD 4 EEE 6 FFF 7 GGG 8

Data Structures & Algorithms Array Representation of Priority Queue: § Use separate queue for

Data Structures & Algorithms Array Representation of Priority Queue: § Use separate queue for each priority level. § Each queue have its own pair of Front and Rear pointers. § Two dimensional array Front Rear 1 2 2 2 3 4 1 3 0 5 0 1 3 5 6 4 4 5 1 2 1 AAA 2 BBB CCC 3 4 6 XXX 4 FFF 6 5 DDD GGG EEE

Data Structures & Algorithms Recursion: Recursion is an important concept in computer science and

Data Structures & Algorithms Recursion: Recursion is an important concept in computer science and many algorithms can be best described in tem of recursion. Suppose P is a procedure containing either a Call statement to itself or a Call statement to a second procedure that may eventually result in a Call statement back to the original procedure P. then P is called recursive procedure. A recursive procedure must have the following two properties: • There must be certain criteria called base case for which the procedure does not call itself. Otherwise the procedure will run indefinitely. • Each time the procedure does call itself, it must be closer to the base case. A recursive procedure with these two properties is said to be well-defined.

Data Structures & Algorithms Factorial: The product of the positive integer from 1 to

Data Structures & Algorithms Factorial: The product of the positive integer from 1 to n is called n factorial, and is usually denoted by n!. n!=1. 2. 3………. (n-3). (n-2). (n-1). n As we know that 0!=1, thus we have: 0!=1 1!=1 2!=2. 1 3!=3. 2. 1=6 4!=4. 3. 2. 1 =24 so on. Observe that 4!=4. 3!=4. 6=24 so For any positive number n, we can write definition of factorial is as: n!=n(n-1)!

Data Structures & Algorithms The factorial function may also be defined as follows: a)

Data Structures & Algorithms The factorial function may also be defined as follows: a) if n=0 then n!=1 b) if n> 0 then n!=n(n-1)! This definition of n! is recursive, since it refer to itself when it uses (n-1)!. The value of n! is explicitly is given when n=0(thus 0 is the base case). The value of n! for n is defined in term of a smaller value of n which is closer to the base value 0. The definition is not circular, the procedure is well- defined.

Data Structures & Algorithms int fact(int n) { int x, y; if(n==0) return 1;

Data Structures & Algorithms int fact(int n) { int x, y; if(n==0) return 1; x=n-1; y=fact(x); return (n*y); } cout<<“Factorial of n=”<<fact(4);

Data Structures & Algorithms fact(4) initially n x y 4 * * 3 4

Data Structures & Algorithms fact(4) initially n x y 4 * * 3 4 n x y n 0 1 2 3 4 n * 0 1 2 3 x * * * y 1 2 3 4 n 0 1 2 3 x 1 * * * y * 3 * * 2 3 4 x y n y=fact(1) y=fact(0) fact(2) fact(3) 2 3 4 1 2 3 n x fact(1) * 2 3 * * * 1 2 3 4 x y n y 3 4 n 2 3 x 2 * y x * * y y=fact(3) y=fact(2) 1 * * * 1 2 3 4 3 n x 6 y

Data Structures & Algorithms Cout<<fact(4); n x y

Data Structures & Algorithms Cout<<fact(4); n x y

Data Structures & Algorithms •

Data Structures & Algorithms •

Data Structures & Algorithms •

Data Structures & Algorithms •

Data Structures & Algorithms int fib (int n) { int x, y; if(n<=1) return

Data Structures & Algorithms int fib (int n) { int x, y; if(n<=1) return n; x=fib(n-1); y=fib(n-2); return (x+y); } cout<<fib(6);

Data Structures & Algorithms a b 6 * * 5 6 n x y

Data Structures & Algorithms a b 6 * * 5 6 n x y n 1 2 3 4 5 6 n f * * * x * * 4 5 6 x y n g * * * y 2 3 4 5 6 n * * * x * * * y 0 2 3 4 5 6 n * * * x h * 1 * * x e d c * * * y 3 4 5 6 n * * x * * y 2 3 4 5 6 n 1 * * x * * * y j i * * * x 0 * * y 3 4 5 6 n 1 * * * x * * y

Data Structures & Algorithms k 1 3 4 5 6 n * 1 *

Data Structures & Algorithms k 1 3 4 5 6 n * 1 * * * x * * * 3 4 5 6 y n p 0 2 4 5 6 n * 1 2 * * x 1 * * * 4 5 6 2 * 3 * * * 2 4 5 6 y n x y n q * * * y 2 4 5 6 n 1 2 * * x n m l r 0 * * * y 4 5 6 n 2 * * x * 2 * * x o * * y 1 2 4 5 6 n y 5 6 n 3 * x * * * y t s 1 * * 2 * * x * * y 3 5 6 * 3 * * n x y

Data Structures & Algorithms Tail recursion: A recursive function call is tail recursive when

Data Structures & Algorithms Tail recursion: A recursive function call is tail recursive when recursive call is the last thing executed by function. A recursive function call is said to be tail recursive if there is nothing to do after the function returns except return its value. int main() { int c; c=fact(5); cout<<c; } int fact(int n) { if (n==0) return 1; else return (n*fact(n-1)); }

Data Structures & Algorithms Tail recursion: int main() { int c; c=factorial(5); cout<<c; }

Data Structures & Algorithms Tail recursion: int main() { int c; c=factorial(5); cout<<c; } int fact(int n , int result) { if (n==0) return result; else return fact(n-1, n*result ); } int factorial(int n) { return fact(n, 1) }

Data Structures & Algorithms Recursive procedure call themselves to work towards a solution to

Data Structures & Algorithms Recursive procedure call themselves to work towards a solution to a problem. In simplementation this balloons as stack is the nesting gets deeper and deeper, reaches the solution, then return through all of the stack frames. This waste is a common complain about recursive programming general.

Data Structures & Algorithms Iterative factorial requires O(1) stack space update n and m

Data Structures & Algorithms Iterative factorial requires O(1) stack space update n and m in place within one stack activation frame each time through the loop int ifact (int n) { int m = 1; while (n > 1) { m = m * n; n = n-1; } return m; }

Data Structures & Algorithms Recursive factorial requires O(n) stack space “Count down” from n

Data Structures & Algorithms Recursive factorial requires O(n) stack space “Count down” from n and delay doing any multiplications until the recursion bottoms out, then do the multiplications on the way “back up” int rfact (int n) { return (n == 0 || n == 1) ? 1 : n * fact(n-1); }

Data Structures & Algorithms The benefits of an elegant recursive description, but equivalent in

Data Structures & Algorithms The benefits of an elegant recursive description, but equivalent in space and time to an iteration requires O(1) stack space instead of O(n) stack space. Written recursively, but only requires O(1) stack space like an iteration. We just need to invoke tfact with m = 1 and compute the expression m*n before the recursive call. The compiler can then do “tail call” optimization and turn the recursion into an iteration automatically. int tfact (int n, int m=1) { return (n == 0 || n == 1) ? m : tfact(n-1, m*n); }

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms

Data Structures & Algorithms