Seminar 4 IT310 Data Structures and Algorithms ( in Java) Instructor : Vladimir Gubanov, PhD Email : [email protected] AIM : vladimirg77 Data Structures and Algorithms in Java Stacks , Queues and Recursion Data Structures and Algorithms in Java Abstract Data Types (ADTs) An abstract data type (ADT) is an abstraction of a data structure An ADT specifies: Data stored Operations on the data Error conditions associated with operations Example: ADT modeling a simple stock trading system The data stored are buy/sell orders The operations supported are order buy(stock, shares, price) order sell(stock, shares, price) void cancel(order) Error conditions: Buy/sell a nonexistent stock Cancel a nonexistent order Abstract data types allow to delay the specific implementation of a data type until it is Stacks on the data. Only after the list of the understood what operations are required to operate 3 Stacks Stacks 4 What is a stack? • • It is an ordered group of homogeneous items of elements. Elements are added to and removed from the top of the stack (the most recently added items are at the top of the stack). Stacks • A stack is a linear data structure that can be accessed only at one of its ends for storing and retrieving data • A stack is called an LIFO structure: last in/first out Data Structures and Algorithms in Java 6 The Stack ADT The Stack ADT stores arbitrary objects Insertions and deletions follow the last-in firstout scheme Think of a spring-loaded plate dispenser Main stack operations: push(object): inserts an element object pop(): removes and returns the last inserted element Stacks Auxiliary stack operations: object top(): returns the last inserted element without removing it integer size(): returns the number of elements stored boolean isEmpty(): indicates whether no elements are stored 7 Push (ItemType newItem) • Function: Adds newItem to the top of the stack. • Preconditions: Stack has been initialized and is not full. • Postconditions: newItem is at the top of the stack. Pop (ItemType& item) • Function: Removes topItem from stack and returns it in item. • Preconditions: Stack has been initialized and is not empty. • Postconditions: Top element has been removed from stack and item is a copy of the removed element. Stacks (continued) Figure 4-1 A series of operations executed on a stack Generally, the stack is very useful in situations when data have to be stored and then retrieved in reverse order. Data Structures and Algorithms in Java 11 Stack Interface in Java public interface Stack<E> { Java interface corresponding to public int size(); our Stack ADT public boolean isEmpty(); Requires the public E top() definition of class throws EmptyStackException; EmptyStackException public void push(E element); Different from the built-in Java class public E pop() java.util.Stack throws EmptyStackException; } Stacks 12 Exceptions Attempting the execution of an operation of ADT may sometimes cause an error condition, called an exception Exceptions are said to be “thrown” by an operation that cannot be executed © 2010 Goodrich, Tamassia Stacks In the Stack ADT, operations pop and top cannot be performed if the stack is empty Attempting the execution of pop or top on an empty stack throws an EmptyStackException 13 Applications of Stacks Direct applications Page-visited history in a Web browser Undo sequence in a text editor Chain of method calls in the Java Virtual Machine Indirect applications Auxiliary data structure for algorithms Component of other data structures © 2010 Goodrich, Tamassia Stacks 14 Method Stack in the JVM The Java Virtual Machine (JVM) keeps track of the chain of active methods with a stack. Each JVM thread has a Java stack containing all currently active methods(only one method can be active – others are suspended) When a method is called, the JVM pushes on the stack a frame containing Local variables and return value Program counter, keeping track of the statement being executed When a method ends, its frame is popped from the stack and control is passed to the method on top of the stack Each method frame includes and operand stack (source of arguments and repository of results) © 2010 Goodrich, Tamassia Stacks main() { int i = 5; foo(i); } foo(int j) { int k; k = j+1; bar(k); } bar(int m) { … } bar PC = 1 m=6 foo PC = 3 j=5 k=6 main PC = 2 i=5 15 Array-based Stack A simple way of implementing the Stack ADT uses an array We add elements from left to right A variable keeps track of the index of the top element Algorithm size() return t + 1 Algorithm pop() if isEmpty() then throw EmptyStackException else tt1 return S[t + 1] … S 0 1 2 t Stack methods have to be implemented. Flexible array can be used (p.146 of your textbook). When © 2010 Goodrich, 16 the stack exceeds theTamassia initial size of the array – aStacks copy to a larger array is created. Array-based Stack (cont.) The array storing the stack elements may become full A push operation will then throw a FullStackException Algorithm push(o) if t = S.length 1 then throw FullStackException else tt+1 Limitation of the arrayS[t] o based implementation Not intrinsic to the Stack ADT … S 0 1 2 © 2010 Goodrich, Tamassia t Stacks 17 Performance and Limitations Performance Let n be the number of elements in the stack The space used is O(n) Each operation (popping and pushing) is executed in the constant time O(1) Limitations The maximum size of the stack is defined a priori and cannot be changed without copying to a larger array (O(n) then) Trying to push a new element into a full stack causes an implementation-specific exception © 2010 Goodrich, Tamassia Stacks 18 Other Implementations of Stack Can be implemented in ArrayList Can be implemented in Linked List Implementation: Includes creating and proper object (of above) Defining pop(), push(), isEmpty(), topEl(), clear() methods see p. Fig 4.4 (p.146) of the textbook for ArrayList ( in next two slides) , Fig 4.5 (p.147) for Linked List No need to define the stack size in advance Stacks 19 ArrayList Stack Implementation Figure 4-4 Array list implementation of a stack Data Structures and Algorithms in Java 20 Stacks (continued) Figure 4-4 Array list implementation of a stack (continued) Data Structures and Algorithms in Java 21 HTML Tag Matching For fully-correct HTML, each <name> should pair with a matching </name> <body> <center> <h1> The Little Boat </h1> </center> <p> The storm tossed the little boat like a cheap sneaker in an old washing machine. The three drunken fishermen were used to such treatment, of course, but not the tree salesman, who even as a stowaway now felt that he had overpaid for the voyage. </p> <ol> <li> Will the salesman die? </li> <li> What color is the boat? </li> <li> And what about Naomi? </li> </ol> </body> © 2010 Goodrich, Tamassia The Little Boat The storm tossed the little boat like a cheap sneaker in an old washing machine. The three drunken fishermen were used to such treatment, of course, but not the tree salesman, who even as a stowaway now felt that he had overpaid for the voyage. 1. Will the salesman die? 2. What color is the boat? 3. And what about Naomi? Stacks 22 Evaluating Arithmetic Expressions 14 – 3 * 2 + 7 = (14 – (3 * 2) ) + 7 Operator precedence * has precedence over +/– Associativity operators of the same precedence group evaluated from left to right Example: (x – y) + z rather than x – (y + z) Idea: push each operator on the stack, but first pop and perform higher and equal precedence operations. Stacks 23 Quadratic Algorithm Algorithm spans1(X, n) Input array X of n integers Output array S of spans of X S new array of n integers for i 0 to n 1 do s1 while s i X[i s] X[i] ss+1 S[i] s return S # n n n 1 + 2 + …+ (n 1) 1 + 2 + …+ (n 1) n 1 Algorithm spans1 runs in O(n2) time © 2010 Goodrich, Tamassia Stacks 24 Linear Algorithm Each index of the array Is pushed into the stack exactly one Is popped from the stack at most once The statements in the while-loop are executed at most n times Algorithm spans2 runs in O(n) time © 2010 Goodrich, Tamassia Algorithm spans2(X, n) # S new array of n integers n A new empty stack 1 for i 0 to n 1 do n while (A.isEmpty() X[A.top()] X[i] ) do n A.pop() n if A.isEmpty() then n S[i] i + 1 n else S[i] i A.top() n A.push(i) n return S 1 Stacks 25 Stacks in java.util package Available as generic stack – extension of Vector class Can be created and initialized as : java.util.Stack stack = new java.util.Stack(); Has five methods ( empty(), peek(), pop(), push(Object el), search(Object el), Stack() Elements can be accessed not at one end only – violation of stack integrity © 2010 Goodrich, Tamassia Stacks 26 Stacks in java.util Figure 4-7 A list of methods in java.util.Stack; all methods from Vector are inherited Data Structures and Algorithms in Java 27 Queues © 2010 Goodrich, Tamassia 28 Queues What is a queue? • It is an ordered group of homogeneous items of • elements. Queues have two ends: – Elements are added at one end. – Elements are removed from the other end. • The element added first is also removed first (FIFO: First In, First Out). queue tail elements enter 4 3 head 2 1 no changes of order elements exit Queues • A queue is a waiting line that grows by adding elements to its end and shrinks by taking elements from its front • A queue is a structure in which both ends are used: – One for adding new elements – One for removing them • A queue is an FIFO structure: first in/first out Data Structures and Algorithms in Java 30 Queue Operations • The following operations are needed to properly manage a queue: – clear() — Clear the queue – isEmpty() — Check to see if the queue is empty – enqueue(el) — Put the element el at the end of the queue – dequeue() — Take the first element from the queue – firstEl() — Return the first element in the queue without removing it Data Structures and Algorithms in Java 31 Queue Specification • Definitions: (provided by the user) – MAX_ITEMS: Max number of items that might be on the queue – ItemType: Data type of the items on the queue • Operations – – – – – MakeEmpty Boolean IsEmpty Boolean IsFull Enqueue (ItemType newItem) Dequeue (ItemType& item) (serve and retrieve) The Queue ADT The Queue ADT stores arbitrary Auxiliary queue objects operations: Insertions and deletions follow object front(): returns the element at the front without the first-in first-out scheme removing it Insertions are at the rear of the integer size(): returns the queue and removals are at the number of elements stored front of the queue boolean isEmpty(): indicates Main queue operations: whether no elements are enqueue(object): inserts an stored element at the end of the queue object dequeue(): removes and returns the element at the front of the queue © 2010 Goodrich, Tamassia Queues Exceptions Attempting the execution of dequeue or front on an empty queue throws an EmptyQueueException 33 Enqueue (ItemType newItem) • Function: Adds newItem to the rear of the queue. • Preconditions: Queue has been initialized and is not full. • Postconditions: newItem is at rear of queue. Dequeue (ItemType& item) • Function: Removes front item from queue and returns it in item. • Preconditions: Queue has been initialized and is not empty. • Postconditions: Front element has been removed from queue and item is a copy of removed element. Queues (continued) Figure 4-8 A series of operations executed on a queue In the difference from Stack, changes need to be monitored at the beginning of the queue and at the end : elements are engueued on one end (right above) and dequeued on the other ( left above). Data Structures and Algorithms in Java 36 Annother Example Operation enqueue(5) enqueue(3) dequeue() enqueue(7) dequeue() front() dequeue() dequeue() isEmpty() enqueue(9) enqueue(7) size() enqueue(3) enqueue(5) dequeue() © 2010 Goodrich, Tamassia – – 5 – 3 7 7 “error” – – 2 – – 9 Output Q (5) (5, 3) (3) (3, 7) (7) (7) () () true () (9) (9, 7) (9, 7) (9, 7, 3) (9, 7, 3, 5) (7, 3, 5) Queues 37 Applications of Queues Direct applications Waiting lists, bureaucracy Access to shared resources (e.g., printer) Multiprogramming Indirect applications Auxiliary data structure for algorithms Component of other data structures Again, queue can be implemented based on Array, ArrayList, Linked List © 2010 Goodrich, Tamassia Queues 38 Array-based Queue Use an array of size N in a circular fashion Two variables keep track of the front and rear f index of the front element r index immediately past the rear element Array location r is kept empty normal configuration Q 0 1 2 f r wrapped-around configuration Q 0 1 2 r f Queue is full when Tamassia the first element is in Queues the first cell or the last element is in the last © 2010 Goodrich, 39 cell , or the first element is right after the last Figure 4-9 Two possible configurations in an array implementation of a queue when the queue is full Data Structures and Algorithms in Java 40 Queue Operations We use the modulo operator (remainder of division) Algorithm size() return (N f + r) mod N Algorithm isEmpty() return (f = r) Q 0 1 2 f 0 1 2 r r Q f Java code implementation of Queue based on Array – see Fig © 2010 Goodrich, Tamassia Queues 41 4.10 of the textbook ; on Linked List – Fig.4.11 ( p.153) Queue Operations (cont.) Operation enqueue throws an exception if the array is full This exception is implementationdependent Algorithm enqueue(o) if size() = N 1 then throw FullQueueException else Q[r] o r (r + 1) mod N Q 0 1 2 f 0 1 2 r r Q © 2010 Goodrich, Tamassia f Queues 42 Queue Operations (cont.) Operation dequeue throws an exception if the queue is empty This exception is specified in the queue ADT Algorithm dequeue() if isEmpty() then throw EmptyQueueException else o Q[f] f (f + 1) mod N return o Q 0 1 2 f 0 1 2 r r Q f In © both Array and Linked List implementation – enqueueing and 2010 Goodrich, Tamassia Queues dequeueing operations are executed in constant time O(1) 43 Queue Interface in Java Java interface corresponding to our Queue ADT Requires the definition of class EmptyQueueException No corresponding built-in Java class © 2010 Goodrich, Tamassia public interface Queue<E> { public int size(); public boolean isEmpty(); public E front() throws EmptyQueueException; public void enqueue(E element); public E dequeue() throws EmptyQueueException; } Queues 44 Applications: Round Robin Schedulers We can implement a round robin scheduler using a queue Q by repeatedly performing the following steps: 1. 2. 3. e = Q.dequeue() Service element e Q.enqueue(e) Queue Dequeue Enqueue Shared Service © 2010 Goodrich, Tamassia Queues 45 Priority Queues • Simple queues are inadequate when first in/first out scheduling has to be overruled using some priority criteria ( e.g. a handicapped person may have priority over others in a post office line) • A priority queue can be assigned to enable a particular process, or event, to be executed out of sequence without affecting overall system operation • In priority queues, elements are dequeued according to their priority and their current queue position Data Structures and Algorithms in Java 46 Priority Queues (continued) • Priority queues can be represented by two variations of linked lists: – in one type : all elements are entry ordered – in another : order is maintained by putting a new element in its proper position according to its priority • Total operational times are usually O(n) Data Structures and Algorithms in Java 47 Summary • A stack is a linear data structure that can be accessed at only one of its ends for storing and retrieving data. • A stack is called an LIFO structure: last in/first out. • A queue is a waiting line that grows by adding elements to its end and shrinks by taking elements from its front. • A queue is an FIFO structure: first in/first out. Data Structures and Algorithms in Java 48 Summary (continued) • In queuing theory, various scenarios are analyzed and models are built that use queues for processing requests or other information in a predetermined sequence (order). • A priority queue can be assigned to enable a particular process, or event, to be executed out of sequence without affecting overall system operation. Data Structures and Algorithms in Java 49 Summary (continued) • In priority queues, elements are dequeued according to their priority and their current queue position. Data Structures and Algorithms in Java 50 Programming with Recursion © 2010 Goodrich, Tamassia Programming with Recursion 51 Recursive Definitions • Recursive definitions are programming concepts that define themselves • A recursive definition consists of two parts: – The anchor or ground case, the basic elements that are the building blocks of all other elements of the set are listed – Rules that allow for the construction of new objects out of basic elements or objects that have already been constructed; these rules are applied again and again to generate new objects – Recursive definitions serve two purposes: generating new elements, and testing whether an element Data Structures and to Algorithms 52 belongs a set.in Java The Recursion Pattern Recursion: when a method calls itself Classic example: the factorial function: n! = 1· 2· 3· ··· · (n1)· n Recursive definition: if n = 0 1 f ( n) = n f (n 1) else Definition above can be easily converted into a Java method: // recursive factorial function public static int recursiveFactorial(int n) { if (n == 0) return 1; // basis case else return n * recursiveFactorial(n- 1); // recursive case } 53 Content of a Recursive Method Base case(s) Values of the input variables for which we perform no recursive calls are called base cases (there should be at least one base case). Every possible chain of recursive calls must eventually reach a base case. Recursive calls Calls to the current method. Each recursive call should be defined so that it makes progress towards a base case. Recursion is calling a method that happens to have the same name as the caller. A recursive call is not literally a method calling itself, but rather an instantiation of a method calling another instantiation of the same original. Programming with Recursion © 2010 Goodrich, Tamassia 54 Using Recursion © 2010 Goodrich, Tamassia Using Recursion 55 Linear Recursion Test for base cases Begin by testing for a set of base cases (there should be at least one). Every possible chain of recursive calls must eventually reach a base case, and the handling of each base case should not use recursion. Recur once Perform a single recursive call This step may have a test that decides which of several possible recursive calls to make, but it should ultimately make just one of these calls Define each possible recursive call so that it makes progress towards a base case. © 2010 Goodrich, Tamassia Using Recursion 56 Example of Linear Recursion Example recursion trace: Algorithm LinearSum(A, n): Input: A integer array A and an integer n = 1, such that A has at least n elements call LinearSum (A,5) Output: call return 13 + A[3] = 13 + 2 = 15 LinearSum (A,4) The sum of the first n integers in A call return 7 + A[2] = 7 + 6 = 13 LinearSum (A,3) if n = 1 then return A[0] else return LinearSum(A, n - 1) + A[n - 1] © 2010 Goodrich, Tamassia return 15 + A[4] = 15 + 5 = 20 Using Recursion call return 4 + A[1] = 4 + 3 = 7 LinearSum (A,2) call return A[0] = 4 LinearSum (A,1) 57 Reversing an Array Algorithm ReverseArray(A, i, j): Input: An array A and nonnegative integer indices i and j Output: The reversal of the elements in A starting at index i and ending at j if i < j then Swap A[i] and A[ j] ReverseArray(A, i + 1, j - 1) return © 2010 Goodrich, Tamassia Using Recursion 58 Defining Arguments for Recursion In creating recursive methods, it is important to define the methods in ways that facilitate recursion. This sometimes requires we define additional paramaters that are passed to the method. For example, we defined the array reversal method as ReverseArray(A, i, j), not ReverseArray(A). © 2010 Goodrich, Tamassia Using Recursion 59 Computing Powers The power function, p(x,n)=xn, can be defined recursively: 1 if n = 0 p( x, n) = x p( x, n 1) else This leads to an power function that runs in O(n) time (for we make n recursive calls). We can do better than this, however. © 2010 Goodrich, Tamassia Using Recursion 60 Recursive Squaring We can derive a more efficient linearly recursive algorithm by using repeated squaring: 1 if x = 0 p( x, n) = x p( x, (n 1) / 2) 2 2 p ( x , n / 2 ) if x 0 is odd if x 0 is even For example, 24 = 2(4/2)2 = (24/2)2 = (22)2 = 42 = 16 25 = 21+(4/2)2 = 2(24/2)2 = 2(22)2 = 2(42) = 32 26 = 2(6/ 2)2 = (26/2)2 = (23)2 = 82 = 64 27 = 21+(6/2)2 = 2(26/2)2 = 2(23)2 = 2(82) = 128. © 2010 Goodrich, Tamassia Using Recursion 61 Recursive Squaring Method Algorithm Power(x, n): Input: A number x and integer n = 0 Output: The value xn if n = 0 then return 1 if n is odd then y = Power(x, (n - 1)/ 2) return x · y ·y else y = Power(x, n/ 2) return y · y © 2010 Goodrich, Tamassia Using Recursion 62 Analysis Algorithm Power(x, n): Input: A number x and integer n = 0 Output: The value xn if n = 0 then return 1 if n is odd then y = Power(x, (n - 1)/ 2) return x · y · y else y = Power(x, n/ 2) return y · y © 2010 Goodrich, Tamassia Using Recursion Each time we make a recursive call we halve the value of n; hence, we make log n recursive calls. That is, this method runs in O(log n) time. It is important that we use a variable twice here rather than calling the method twice. 63 Tail Recursion All recursions contain a reference to a set or function to be defined Can be implemented in different ways Tail recursion is using only one recursive call at the very end of method implementation – when a call is made , there is no statements left to execute in that method © 2010 Goodrich, Tamassia Stacks 64 Tail Recursion Example Tail recursion is characterized by the use of only one recursive call at the very end of a method implementation void tail (int i) { if (i > 0) { System.out.print (i + ""); tail(i-1); } } 65 Tail recursion can be easily replaced by a loop ( see p.179) NonTail Recursion Example Example of nontail recursion: void nonTail (int i) { if (i > 0) { nonTail(i-1); System.out.print (i + ""); nonTail(i-1); } } 66 Tail Recursion Tail recursion occurs when a linearly recursive method makes its recursive call as its last step. The array reversal method is an example. Such methods can be easily converted to nonrecursive methods (which saves on some resources). Example: Algorithm IterativeReverseArray(A, i, j ): Input: An array A and nonnegative integer indices i and j Output: The reversal of the elements in A starting at index i and ending at j while i < j do Swap A[i ] and A[ j ] i =i+1 j =j-1 return © 2010 Goodrich, Tamassia Using Recursion 67 Indirect and Nested Recursion Direct recursion - a method calls itself Indirect recursion - a method calls itself via a chain of other calls : f() -> f1() -> f2() -> · · · -> fn() -> f() A function is defined in terms of itself and used as one of its parameters: 0 if n=0 h(n) = { n if n>4 h(2 + h(2n) if n< 4 68 Binary Recursion Binary recursion occurs whenever there are two recursive calls for each non-base case. Example: the DrawTicks method for drawing ticks on an English ruler. © 2010 Goodrich, Tamassia Using Recursion 69 A Binary Recursive Method for Drawing Ticks // draw a tick with no label public static void drawOneTick(int tickLength) { drawOneTick(tickLength, - 1); } // draw one tick public static void drawOneTick(int tickLength, int tickLabel) { for (int i = 0; i < tickLength; i++) System.out.print("-"); if (tickLabel >= 0) System.out.print(" " + tickLabel); Note the two System.out.print("\n"); recursive calls } public static void drawTicks(int tickLength) { // draw ticks of given length if (tickLength > 0) { // stop when length drops to 0 drawTicks(tickLength- 1); // recursively draw left ticks drawOneTick(tickLength); // draw center tick drawTicks(tickLength- 1); // recursively draw right ticks } } public static void drawRuler(int nInches, int majorLength) { // draw ruler drawOneTick(majorLength, 0); // draw tick 0 and its label for (int i = 1; i <= nInches; i++) { drawTicks(majorLength- 1); // draw ticks for this inch drawOneTick(majorLength, i); // draw tick i and its label } } © 2010 Goodrich, Tamassia Using Recursion 70 Another Binary Recusive Method Problem: add all the numbers in an integer array A: Algorithm BinarySum(A, i, n): Input: An array A and integers i and n Output: The sum of the n integers in A starting at index i if n = 1 then return A[i ] return BinarySum(A, i, n/ 2) + BinarySum(A, i + n/ 2, n/ 2) Example trace: 0, 8 0, 4 4, 4 0, 2 0, 1 2, 2 1, 1 © 2010 Goodrich, Tamassia 2, 1 4, 2 3, 1 4, 1 Using Recursion 6, 2 5, 1 6, 1 7, 1 71 Computing Fibonacci Numbers Fibonacci numbers are defined recursively: F0 = 0 F1 = 1 Fi = Fi-1 + Fi-2 for i > 1. Recursive algorithm (first attempt): Algorithm BinaryFib(k): Input: Nonnegative integer k Output: The kth Fibonacci number Fk if k = 1 then return k else return BinaryFib(k - 1) + BinaryFib(k - 2) © 2010 Goodrich, Tamassia Using Recursion 72 Analysis Let nk be the number of recursive calls by BinaryFib(k) n0 = 1 n1 = 1 n2 = n1 + n0 + 1 = 1 + 1 + 1 = 3 n3 = n2 + n1 + 1 = 3 + 1 + 1 = 5 n4 = n3 + n2 + 1 = 5 + 3 + 1 = 9 n5 = n4 + n3 + 1 = 9 + 5 + 1 = 15 n6 = n5 + n4 + 1 = 15 + 9 + 1 = 25 n7 = n6 + n5 + 1 = 25 + 15 + 1 = 41 n8 = n7 + n6 + 1 = 41 + 25 + 1 = 67. Note that nk at least doubles every other time That is, nk > 2k/2. It is exponential! © 2010 Goodrich, Tamassia Using Recursion 73 A Better Fibonacci Algorithm Use linear recursion instead Algorithm LinearFibonacci(k): Input: A nonnegative integer k Output: Pair of Fibonacci numbers (Fk , Fk1) if k = 1 then return (k, 0) else (i, j) = LinearFibonacci(k 1) return (i +j, i) LinearFibonacci makes k1 recursive calls © 2010 Goodrich, Tamassia Using Recursion 74 Multiple Recursion Motivating example: summation puzzles pot + pan = bib dog + cat = pig boy + girl = baby Multiple recursion: makes potentially many recursive calls not just one or two © 2010 Goodrich, Tamassia Using Recursion 75 Algorithm for Multiple Recursion Algorithm PuzzleSolve(k,S,U): Input: Integer k, sequence S, and set U (universe of elements to test) Output: Enumeration of all k-length extensions to S using elements in U without repetitions for all e in U do Remove e from U {e is now being used} Add e to the end of S if k = 1 then Test whether S is a configuration that solves the puzzle if S solves the puzzle then return “Solution found: ” S else PuzzleSolve(k - 1, S,U) Add e back to U {e is now unused} Remove e from the end of S © 2010 Goodrich, Tamassia Using Recursion 76 Summary • Recursive definitions are programming concepts that define themselves • Recursive definitions serve two purposes: – Generating new elements – Testing whether an element belongs to a set • Recursive definitions are frequently used to define functions and sequences of numbers Data Structures and Algorithms in Java 77 Summary (continued) • Tail recursion is characterized by the use of only one recursive call at the very end of a method implementation. • No general rules for when to use it and when to use it. Each particular problem decides. • Recursion is usually less efficient than its iterative equivalent. • Recursion is often simpler than the iterative solution • Every recursive method can be converted into an iterative version • Sometimes a recursive version is faster than a nonrecursive implementation. Data Structures and Algorithms in Java 78 Quck Quiz 1. What is a recursion ? 2. Can a recursion do something which iteration cannot ? 3. Can a recursion take less coding than iteration? 4. : Does using recursion usually make your code faster? 5. Does using recursion usually use less memory? 6. Then why use recursion? Data Structures and Algorithms in Java 79 Quite a number of good sites on recursion are available on the WEB - below are just some : http://cplus.about.com/od/glossar1/g/recursiondefn.htm http://www.sharpened.net/glossary/definition.php?recursive function and many more. Recursion might look unusual and confusing at first, but it serves well in many cases... Data Structures and Algorithms in Java 80
© Copyright 2026 Paperzz