1 / 24

Recursion on linked lists

Recursion on linked lists. All the linked list examples we have seen so far use iteration when they need to work through the nodes of a list (for example, to print nodes or search for particular values). We could alternatively use recursion. often neater than iteration

viet
Télécharger la présentation

Recursion on linked lists

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. Recursion on linked lists • All the linked list examples we have seen so far use iteration when they need to work through the nodes of a list (for example, to print nodes or search for particular values). • We could alternatively use recursion. • often neater than iteration • a useful introduction to recursion on linked structures • has hidden costs that you need to understand to use it safely.

  2. Why use recursion • For more complex linked data structures, recursive methods are generally better than iterative ones • easier to understand • easier to write • efficient • Recursion on linked lists is useful learning exercise.

  3. Example – recursively printing nodes • Our Linked list class had a print() method that printed out the names and numbers from each of the nodes of the list in order. • We could do this recursively instead. // Print out the entries in the list, one per line. public void print() { for (Node n = first; n != null; n = n.next) System.out.println(n.name + " " + n.number); }

  4. // Print out the entries in the list, // one per line. public void printr() { printr(first); } // Recursively print out the list starting at // start_node private void printr(Node start_node) { if (start_node == null) return; System.out.println(start_node.name + " " + start_node.number); printr(start_node.next); }

  5. Perspectives on recursion • Sanity check • How does it work? • How can I create a recursive solution to my problem? • What is going on behind the scenes? • What are the costs?

  6. Recursion Sanity Check • The recursive call should always be on a smaller data structure than the current one. • There must always be a non-recursive option if the data-structure is too small. • You often need a wrapper method to make the recursive method accessible. • in this case, the no-parameter printr() method

  7. How to understand how a recursive method works • Start off by working through what happens when it is called with a null list (no recursion happens). • Work through what happens when the list has only one node. • Look at 2 nodes • ...

  8. How to write a recursive method • Suppose that you have an operation that you want to perform on a linked list: • Decide what to do if the list is empty. • Imagine that you are looking at the first node of a list and have already written the method so that you can use it on the remaining list. • Think how to put together a working algorithm for the whole list from your knowledge of the first node and the results of calling the (still unwritten) method for the rest of the list.

  9. Example: print out list nodes in reverse order • If the list is empty then the answer is to do nothing. • Now imagine that you have written the method and can use it on the remainder of the list after the first node. • To print out all the nodes in reverse order you call the the method to print the remaining nodes in reverse order then print out the first node.

  10. Reverse printing code // Recursively print out the list in reverse // order. private void printr_rev(Node start_node) { if (start_node == null) return; printr_rev(start_node.next); System.out.println(start_node.name + " " + start_node.number); }

  11. It seems too good to be true • How could you do it without recursion? • reverse the order of the list, print out the nodes then reverse it again. • use an auxiliary data structure (a stack, say) to store the values as you iterate forward through the list. Then use the stored data to print out the values once you have reached the end of the list. • Both these are fiddly to program yet the recursive print method does it just by reversing the order of two lines of code.

  12. Stack Frames • Local Java method variables and parameters are created each time the method is called and destroyed when the method returns. • This is done on a stack, and the space used by an active method is called its stack frame • In addition to your local variables and parameters the stack frames can contain information used by debuggers and to generate diagnostics if the program crashes.

  13. Example class MyClass { public static void main(String[] args) { MyClass mc = new MyClass(); foo(42); bar(); } void foo(int n) { bar(); } void bar() { int j = 7; } }

  14. Method call walk-through Method stack Active Methods main's stack frame args ... main

  15. Method call walk-through Method stack Active Methods main's stack frame args ... main foo foo's stack frame n [42]

  16. Method call walk-through Method stack Active Methods main's stack frame args ... main foo bar foo's stack frame n [42] bar's stack frame j [7]

  17. Method call walk-through Method stack Active Methods main's stack frame args ... main foo foo's stack frame n [42]

  18. Method call walk-through Method stack Active Methods main's stack frame args ... main

  19. Method call walk-through Method stack Active Methods main's stack frame args ... main bar bar's stack frame j [7]

  20. Method call walk-through Method stack Active Methods main's stack frame args ... main

  21. Recursive method calls • Recursive methods are the same as none-recursive – each active method has its own stack frame. • Each recursive printr() method will have its own stack frame containing (at least) the start_node parameter it was called with. • After printr() has been called on the last node of a 1000 node list there will be 1000 printr() stack frames on the method stack.

  22. Print-order • Both the forward and the reverse print methods generate a stack-frame for each node in the list. and also call println for each node in the list. • The difference is that the printr() method does its output as it is creating the stack. Then when it gets to the null at the end each of the printr() methods returns without doing anything else. • The printr_rev() does not produce any output as it is building the stack but does does it as the methods are returning and the stack is being dismantled.

  23. Stack Overflow • Java VM method-stack space is limited and a program will crash if the space runs out. • also true for other procedural languages like C • It is not a good idea to use recursion if the recursive method calls can go thousands deep. • e.g. printing out a long linked list.

  24. Sorting a linked list • It is possible to use quicksort on a linked list but it is rather clumsy, and finding the middle node for the pivot is expensive. • Fortunately, there is another sorting algorithm, mergesort, that works well on linked lists but does not work on arrays. • Mergesort, like quicksort, is an n*logn algorithm but unlike quicksort it does not have any bad worst-case performance.

More Related