The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #1 Lecture #10 - Design with Interfaces, Recursion, Trees In this lecture: Some examples of design with interfaces Runtime Stack Recursion Trees and algorithms on trees
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #2 The Clock Alarm Problem Recall the Alarm Clock Example Whenever the alarm time has been reached, an “alarm event” occurred, which caused the alarm clock to activate an alarm In your exercise, the clock opened a window with the proper alarm message This is not general enough: We wish to have a technique which enables us to invoke a method on an arbitrary object of our choice when an alarm occurs Sometimes there are several objects which are interested in this event
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #3 Multiple Listeners to an Event Alarm
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #4 The “Observer-Observable” Pattern This pattern enables several “observers”, which are interested in a certain event, to get notified when this event occurs The event is generated by an “observable” object Sometimes the “observers” are called “listeners” To get notified about an event, an observer registers itself at the observable object The observable maintains a list of interested observers, and notifies them when the event occurs
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #5 Example: Alarm Clock /** * A listener interface for receiving alarm events * from a clock */ public interface AlarmClockListener { public void alarmActivated(AlarmEvent e); } public class AlarmEvent { Object eventSource; public AlarmEvent(Object EventSource) { this.eventSource = eventSource; }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #6 Example: Alarm Clock public AlarmClock extends Clock { private Clock alarmTime; private Vector listeners; // constructor... public void secondElapsed() { super.secondElapsed(); if (alarmTimeReached()) { notifyListeners(); } // returns true if alarm time has been reached private boolean alarmTimeReached() { if (getHours() == alarmTime.getHours() && getMinutes() == alarmTime.getMinutes() && getSeconds() == alarmTime.getSeconds()) return true; return false; }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #7 Example: Alarm Clock /** * Adds an alarm listener to this clock */ public void addAlarmClockListener(AlarmClockListener listener) { listeners.add(listener); } /** * Notifies all alarm listeners of an alarm event */ private void notifyListeners() { AlarmEvent event = new AlarmEvent(this); for (int i = 0; i < listeners.size(); i++) { AlarmClockListener listener = (AlarmClockListener)listeners.getElementAt(i); listener.alarmActivated(event); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #8 Example: Alarm Clock public class InterestedListener implements AlarmClockListener { // … public InterestedListener(…) { //... } public void alarmActivated(AlarmEvent event) { System.out.println(“Wake me up before you go go”); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #9 GUI Components: Observable Objects Java GUI components are observable objects This means that any listener can register for events fired from any GUI component For example, a button can fire an “action performed” event whenever it is pressed Interested objects can register themselves as listeners to an “action event” fired by a button and implement the ActionListener interface
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #10 Example: Button import java.awt.*; import java.awt.event.*; public class ButtonExample extends Frame implements ActionListener { private Button button = new Button(“press!”); public ButtonExample() { add(button); button.addActionListener(this); } public void actionPerformed(ActionEvent e) { System.out.println(“Button Clicked”); } public static void main(String[] args) { Frame f = new ButtonExample(); f.setSize(100,100); f.setVisible(true); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #11 The Runtime Stack During the execution of a program, there is a sequence of method calls The interpreter (or the operating system) has to keep track of the calling sequence and of the parameters This is done in the main memory using a runtime stack A copy of each formal formal parameter (the actual parameter), which can be a primitive type or a reference, is pushed onto the stack
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #12 Example: Runtime Stack public class Test { public static void main(String[] args) { f(3,2); } public static void f(int a, int b) { Point p = new Point(a,b); g(p,9); h(); } public static void g(Point p, int c) { p.setX(5); p.setY(7); c = 15; } public static void h() { //... }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #13 main
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #14 f a = 3 b = 2 main
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #15 g p = Point(3,2) c = 9 f a = 3 b = 2 main
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #16 f a = 3 b = 2 main
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #17 f a = 3 b = 2 main h
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #18 f a = 3 b = 2 main
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #19 main
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #20 Recursion -- Introduction Recursion is a fundamental programming technique that can provide an elegant solution certain kinds of problems Recursion is often used in programs In certain cases recursion dramatically simplifies the readability of a program, and provides a simple solution to complex problems
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #21 Recursive Thinking A recursive definition is one which uses the word or concept being defined in the definition itself Consider the definition: A folder is a collection of zero or more file and/or folders When defining a folder we use the defined term in the definition body.
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #22 Recursive Definitions Consider the following list of numbers: 24, 88, 40, 37 Such a list can be defined as A LIST is a: number or a: number comma LIST That is, a LIST is defined to be a single number, or a number followed by a comma followed by a LIST The concept of a LIST is used to define itself
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #23 Recursive Definitions The recursive part of the LIST definition is used several times, terminating with the non-recursive part: number comma LIST 24, 88, 40, 37 number comma LIST 88, 40, 37 number comma LIST 40, 37 number 37
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #24 Infinite Recursion All recursive definitions have to have a non- recursive part If they didn't, there would be no way to terminate the recursive path Such a definition would cause infinite recursion This problem is similar to an infinite loop, but the non-terminating "loop" is part of the definition itself The non-recursive part is often called the base case
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #25 Recursive Definitions N!, for any positive integer N, is defined to be the product of all integers between 1 and N inclusive This definition can be expressed recursively as: 1! = 1 N! = N * (N-1)! The concept of the factorial is defined in terms of another factorial Recursive definitions are common in mathematics
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #26 Recursive Definitions 5! 5 * 4! 4 * 3! 3 * 2! 2 * 1!
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #27 Recursion - Yet Another Form of Reduction When we have a problem that can be defined recursively, we can solve it using recursion When we solve a problem using recursion, we reduce the problem to a problem that is similar to the original and is different only by a parameter Example: Problem p(5) - compute 5!. 5!=4!*5, so we can reduce the problem to the problem of finding 4!. But 4!=3!*4, so we can reduce further. We end up with the problem of finding 1! which is simple.
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #28 Recursive Programming - Behind the Scenes A method in Java can invoke itself; if set up that way, it is called a recursive method The code of a recursive method must be structured to handle both the base case and the recursive case Each call to the method sets up a new execution environment, with new parameters and local variables As always, when the method completes, control returns to the method that invoked it (which may be an earlier invocation of itself)
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #29 Example - n! public static long factorial(long n) { if (n == 0) { return 1; } return n * factorial(n-1); } public static long factorial(long n) { return (n == 0) ? 1 : n * factorial(n-1); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #30 Example: Sum of Integers - Definition Consider the problem of computing the sum of all the numbers between 1 and any positive integer N This problem can be recursively defined as: i = 1 N N-1 i = 1 N-2 i = N +i = N +(N-1)+i +...
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #31 Example - Sum of Integers - Program // Compute the sum of the series 1,2,..,n // n is given as a command line argument class ArithmeticalSum { public static void main(String[] args) { int n = Integer.parseInt(args[0]); System.out.println(sum(n)); } static int sum(int n) { return (n == 1) ? 1 : n + sum(n-1); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #32 Sum of Integers Call Stack main sum sum(3) sum(1) sum(2) result = 1 result = 3 result = 6
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #33 When Should Recursion be Used? Note that just because we can use recursion to solve a problem, doesn't mean we should For instance, we usually would not use recursion to solve the sum of 1 to N problem, because the iterative version is easier to understand However, for some problems, recursion provides an elegant solution, often cleaner than an iterative version You must carefully decide whether recursion is the correct technique for any problem
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #34 Example Depth First Search (DFS) Recall the definition of the term folder Suppose we want to list all the files under a given folder. We can do it as follows: list folders under(Folder f) : Let L be the list of all files and folders directly under f. For each element f1 in L : if f1 is a folder : list folders under f1 otherwise : print the name of f1
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #35 File Listing Example import java.io.File; // List all the files under a given folder // Usage: java ListFiles class ListFiles { /** * List of the files under a given folder * given as an argument. */ public static void main(String[] args) { listFiles(new File(args[0])); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #36 File Listing Example // List all files under a given folder public static void listFiles(File folder) { String[] files = folder.list(); for (int i=0; i<files.length; i++) { File file = new File(folder, files[i]); if (file.isDirectory()) { listFiles(file); } else { System.out.println(file); }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #37 Indirect Recursion A method invoking itself is considered to be direct recursion A method could invoke another method, which invokes another, etc., until eventually the original method is invoked again For example, method m1 could invoke m2, which invokes m3, which in turn invokes m1 again This is called indirect recursion, and requires all the same care as direct recursion It is often more difficult to trace and debug
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #38 Indirect Recursion m1m2m3m1m2m3m1m2m3
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #39 Example: Maze A maze is solved by trial and error -- choosing a direction, following a path, returning to a previous point if the wrong move is made As such, it is another good candidate for a recursive solution The base case is an invalid move or one which reaches the final destination Solving a maze can be done in a similar manner to that of listing the files under a given directory.
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #40 ddddd dd d d dd dddd ddddd d d dd dddd d d
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #41 Example: Binary Search Binary Search(element, left, right, arr) if (left == right) // termination condition return (arr[left] == element); else { middle = (left + right) / 2; if (a[middle] < element) Binary Search(element,left,middle-1,arr); if (a[middle] > element) Binary Search(element,left+1,right,arr); return true; // a[middle] == element; }
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #42 Example: Binary Tree Definition: A binary tree is: A leaf (a single vertex) or a vertex connected to two disjoint binary trees, left tree and right tree
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #43 A Binary Tree A D CB E GH F I
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #44 Example: Expression Tree + / -*
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #45 Definition of Expression: Resemblance to Tree An Expression is: A number or (exp1 op exp2) where exp1 and exp2 are expressions, op is an operator
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #46 An Interface to Trees for a tree t: t.leftSubTree() returns the left sub-tree of t t.rightSubTree() returns the right sub-tree of t t.isLeaf() returns true if t is a leaf t.getRoot() returns the value of the root
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #47 Computing the Value of an Expression Tree int Expression Tree Value(t) if (t.isLeaf()) return t.getRoot() else int left = Expression Tree Value(t.leftSubTree()); int right = Expression Tree Value(t.rightSubTree()); operator op = t.getRoot(); return (left op right); // switch to cases...
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #48 Printing a Tree Inorder: print left subtree, print root, print right sub tree Preorder: print root, print left subtree, print right subtree Postorder: print left subtree, print right subtree, print root
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #49 Polish Notation Definition: The polish notation of an expression is the postorder scan of the tree Example: For the binary tree presented earlier, the polish notation representation is: 7 3 / 2 * Computing a polish notation expression value: using a stack
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #50 Some Facts on Trees A tree with n vertices has n-1 edges A full binary tree with k levels has has … + 2 k = 2 k vertices. If the binary tree is not full, then it has at least k+1 vertices. What is the height of a binary tree with n vertices? (number of levels)? A full binary tree has height has k = O(log n) levels. A “slim” binary tree has k = O(n) levels.
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #51 Binary Search Tree A binary tree with a special restriction: at each vertex, the value of the vertex is greater than or equal to any vertex in the left subtree, and smaller than any vertex in the right subtree
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #52 Example: Binary Search Tree
The Interdisciplinary Center, Herzelia Lecture 10, Introduction to CS - Information Technologies Slide #53 Algorithms on Binary Trees Printing in order: inorder… Finding an element: recursion… Finding minimal element: Base case: if leaf or empty left subtree, return root Recursion: return minimum of left subtree.