Recursion Question : Revision - java

My slides say that:
A recursive call should always be on a smaller data structure than the current one
There must be a non recursive option if the data structure is too small
You need a wrapper method to make the recursive method accessible
Just reading this from the slides makes no sense, especially seeing as it was a topic from before christmas!
Could anyone try and clear up what it means please?
Thank you

A recurssive call should always be on a smaller data structure than the current one
In general this isn't true but if you are talking about linked lists manipulation with recursion it is. What it is implying is that you need to always be working towards a solution and this usually is dealing with a smaller problem than you started with.
Take for example Quicksort. Each time the function is called it is working with a smaller set of data.
Taking another example of printing a linked list, the next time you call the recursive function the argument should be the tail of the linked list (This code has an error in it, but that leads us to our next point)
void printList(List l){
print(l.head);
printList(l.tail);
}
There must be a non recurssive option if the data structure is too small
This means there should be a base case. The point where the function stops calling itself again.
int factorial(int n){
if ( n == 1 ){ //the base case is when n = 1
return 1;
}
return n*factorial(n-1);
}
Going back to the example of printing a linked list, there has to be a case where you only have an empty list left (in which case the function should do nothing). Going back to the code to print a linked list
void printList(List l){
if ( l.empty == true ){ //the base case is when the list l is empty
return;
}
print(l.head);
printList(l.tail);
}
You need a wrapper method to make the recurssive method accessible
I don't know Java, and it isn't really a language designed for recursion, however in many cases your recursive function will have more parameters than the person using the API should be able to see. You might for example want to have a counter in there.
You can have a wrapper function that simplifies the parameters to just what is needed. The wrapper function then calls the real worker function.
An example might be if we have a linked list class that has the recursive function to print the list. Its declaration would look something like this:
void printList(List l);
However as it is a class method, to someone using the API it doesn't make much sence to have to do this:
myList.printList(myList);
So a wrapper function could be created that doesn't have any paramters which then calls the code that does the work.
void printList(){
doPrintList(this); //pass in the List object as the first argument
}
Then all the programmer using the API has to do is:
myList.printList();

Related

Does the compiler optimise the parameters that does not change?

class X
{
public static void func(int timesLeft, Object obj)
{
if (timesLeft-- == 0)
return;
System.out.println(obj);
func(timesLeft, obj);
}
}
In this code it's obvious that the parameter timesLeft changes, but obj is the same for all function calls. Does obj get passed and put on a stack frame for each call or does the compiler notice that it's the same object each time and applies some optimizations such that all the calls access the same location for the second parameter (obj) instead of each call having its own parameter?
Edit:
This example is just a simplified one. There are some situations where processing some data structure needs recursion. For example exploring graphs. If I want to apply dfs on a graph for example, I would want to keep track of visited nodes (maybe by using a boolean[]). Since this boolean array is specific to the function and isn't used elsewhere , it doesn't make sense to store it as a field or something. probably the best thing to do is to pass it to every call. So I was wondering does the compiler optimise something like that or not but with a simpler exmple.

Sorting Implementation, same test case

i have sth like: ( X - different algorithms)
public class XAlgorithm{
sort(List l){...}
}
In testClass it present as follows:
ArrayList array = new ArrayList(...); // original array
public static void main(String[]args){
AlgorithmsTest at = new AlgorithmsTest();
at.testInsertSort();
// when add at.array.printAll() - method printing all elements, there are no changes to original array what I want
at.testBubbleSort();
at.testSelectSort();
at.testShellSort();
}
testBubbleSort{
...
ArrayList arrayBubble = new ArrayList(testBubble.sort(array));
...
}
Problem is my result ( time measured by System.currentTimeMilis() ) is different when i launch for ex. two times in a row the same algorithm, it's also strange because even when I done copying in every method ( by putting all new Elements into new array and then operate on it) still works wrong. Time is always greatest for first algorithm in main no matter which one it is.
I even controlled array between every algorithm ( like //comment in code above) and it is right - no changes to it, so where is the problem :/ ?
Thanks in advance
Even though you stated you're making a copy of the array, it sounds like you're sorting in place and then making a copy of the array.
Therefore, the first time is going to take longest, but all subsequent runs have less work to do because the array is "sorted".
It also seems to say that your sort algorithms have bugs in it, such that you're getting close on the first sort (or it is right) but then a subsequent sort is finding a corner case, causing a slight variation in the sorted array. I'd be analyzing my sort methods and make sure they're working as you intended.

Java: easily peek backwards or forwards in a list

I'm coding a lexical analyzer in java and need to look backwards or forwards easily in a list of custom datatypes (my tokens). I've tried saving the next and previous item as a copy, but then I figured out that I need to look arbitrarily far ahead or back. I then tried to use an index, but it was beyond unpleasant to debug that since I had to think about decreasing, increasing and getting the current position in a pinch (I even had the objects store an int of where they were at) all the while keeping within range of the list, so it was an ugly, hard to read mess of spaghetti code too at that.
I then looked into linked lists, but they don't quite work like I want them too. I want a node and I want to be able to look ahead for two or three positions, or back, and I didn't really find any good tools for that at that place.
Right now, I'm trying out iterators but I have the same problem as with indexes: I have to decrease and increase back again to where I was at since next() moves the cursor instead of just "peeking ahead".
I'm thinking of coding my own linked list and just hitting node.next().next() if I want to go two steps forward, or a loop repeatedly hitting it if I want to go longer than that. Is there any built in way in Java saving me from this?
You're getting spaghetti code because you're not following SoC. One way to help yourself is to create a specialized collection class that implements functions which, for your problem domain, hide the ugly particulars of array navigation such as tracking the current position, iterating N steps back and forth, "peeking" back and forth, etc.
There are a hundred ways to do this but in my code sample below I chose to compose with rather than extend the ArrayList<> class. I chose ArrayList<> because of its random access capabilities and chose not to extend to help stay away from manipulating the ArrayList<> directly from client code and getting back into a spaghetti mess. I wasn't considering performance but as it happens that ArrayList<>'s random access functions are mostly O(1) rather than O(n) which you would get if you used an iterator or linked list. With those collection types you would also be forced to traverse through the collection just to peek at an object which hurts performance further and also makes implementation that much harder.
Here is a link to an Ideone implementation of my suggested solution. It is a bit different from the code shown below due to the complexities imposed by an online Java compiler but the code is easily accessible and fully executable.
Code sample notes: This is a full, working sample which contain three classes necessary to demostrate the concepts. There is a class to hold the main function which demonstrates usage of the collection class and also acts as a poor-man's unit test. There is a POJO-style class to represent a node or token and finally the utility class which exposes a specialized set of functions, or API. The code is very basic and naive. There is no error or bounds checking of any kind but it demonstrates my suggestion fairly well, IMHO.
To the code! Here is the main function which initializes the NodeList with an arbitrary, Java-like line of code and then proceeds to peek and move in the token list. Note that there is no variable needed in the client code to track what's going on. The navigation is all handled within the NodeList class. The client code's concerns now do not include that ugliness.
import java.util.*;
import java.io.*;
public class TestNodeList {
public static void main(String[] args) {
// usage: basic initialization
NodeList nl = new NodeList();
nl.add(new Node("someUtilObj"));
nl.add(new Node("."));
nl.add(new Node("print"));
nl.add(new Node("("));
nl.add(new Node("myIntValue"));
nl.add(new Node(")"));
nl.add(new Node(";"));
nl.print();
// usage: using the API, moving and peeking
nl.peekAhead(1).print();
nl.peekAhead(2).print();
nl.peekAhead(3).print();
nl.moveAhead(2).print();
nl.getCurrentNode().print();
nl.peekBack(2).print();
}
}
This is the implementation of the specialized collection with some fields and functions I assume would be useful for your lexical analysis. Again, it is quite bare but covers the more important concepts.
public class NodeList {
private ArrayList<Node> nodeList = new ArrayList<Node>();
private int currentNodeIndex = 0;
public void add(Node node) {
nodeList.add(node);
}
// Node is private/read-only - currentNode should only be set by internal operations
public Node getCurrentNode() {
return nodeList.get(currentNodeIndex);
}
// moving back and forth
public Node moveAhead(int count) {
currentNodeIndex += count;
return nodeList.get(currentNodeIndex);
}
public Node moveBack(int count) {
currentNodeIndex -= count;
return nodeList.get(currentNodeIndex);
}
// peeking back and forth
public Node peekAhead(int count) {
return nodeList.get(currentNodeIndex + count);
}
public Node peekBack(int count) {
return nodeList.get(currentNodeIndex - count);
}
public void print() {
for (int i=0; i<nodeList.size(); i++) {
System.out.print(nodeList.get(i).getToken());
}
System.out.println("");
}
}
Other functions to consider implementing for a better, cleaner API:
peekNext() - same as peekAhead(1) but w/o the magic number. I would think that this would also be the most frequently called function in your specialized collection so it makes sense to have a shorter, cleaner version of the operation than peekAhead(1)
peekPrev() - same as peekBack(1) but w/o the magic number
moveNext() - same as moveAhead(1) but w/o the magic number. This would also be a frequently called function in your API and a cleaner version of moveAhead(1)
movePrev() - same as moveBack(1) but w/o the magic number
peekAt(int) - Peek at an element at a specific index in the collection
jumpTo(int) - Move current position to an element at a specific index in the collection
moveFirst() - Resets your current position to the 0th element in the collection
Here are a few more but I'm not sure they would be very useful:
moveLast() - Sets current position to the last element in the collection
peekFirst() - Peek at the 0th element in the collection
peekLast() - Peek at the last element in the collection
To properly implement the functions listed above you should stay consistent and treat them almost like overloads. So, for example, internally peekNext() would actually just call peekAhead(1). This would keep your API's behavior consistent and simpler to maintain in case the implementation of the core function, peekAhead, needs to change.
And finally, here's the POJO. It just contains a single field, the token value, and a function to help write the value to console. Notice that the class does not have an index to itself because it isn't necessary.
// Your node/token class
public class Node {
private String token;
public Node(String token) {
this.token = token;
}
public String getToken() {
return token;
}
public void print() {
System.out.println(token);
}
}
For traversing forward and backwards you can use ListIterator instead of Iterator. You can get it from the LinkedList:
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#listIterator(int)

Build Binary Tree from Preorder Traversal: Stack Overflow Error

I have a tree where the leaves are marked with L and the non-leaf nodes are marked with I. I am given the preorder traversal of the tree. An example is IIILLILILLIIILLLIILILLL. I have to build the huffman tree for this included string. I originally pass in a new Root(), 0, and my treeString for my arguments. TreeString would be the string with the I's and L's pasted above. For some reason my code causes a StackOverflow exception to be thrown. My code is as follows for the makeTree method:
public static void makeTree (BinaryNodeInterface<Character> root, int start, String treeString)
{
if (treeString.charAt(start)=='L'){
root.setLeftChild(null);
root.setRightChild(null);
return;
}
BinaryNodeInterface<Character> leftSide = new BinaryNode<Character>();
root.setLeftChild(leftSide);
makeTree(root.getLeftChild(), start++, treeString);
BinaryNodeInterface<Character> rightSide = new BinaryNode<Character>();
root.setRightChild(rightSide);
makeTree(root.getRightChild(), start++, treeString);
}
I have no idea what is causing the stackoverflow exception to be thrown. I would think that my base case at the beginning would return and handle it.
I believe this is the problem:
makeTree(root.getLeftChild(), start++, treeString);
I'm not sure what your approach is, but it looks like if you see an I, your plan is to go to the left node, and start examining the string starting at the next character.
The reason for the infinite recursion is that start++ is a post-increment operator, which means that it gives you the current value of start and then increments it. Thus, each time makeTree calls itself, it calls itself with the same version of start, and thus looks at the same I in the input string.
However, changing it to ++start will not make things work. (It might avoid the stack overflow, but it won't work right.) The reason is that when you call makeTree, you want to give it the starting location of the string where you want the recursive call to start looking--but you also want the recursive call to tell it how much of the string it consumed. That is necessary because, after makeTree calls itself recursively on getLeftChild, you will call it again on getRightChild, and you need to call it with the correct starting point.
Note that each recursive invocation has its own copy of start. Thus, when makeTree calls itself, and the second makeTree increments start, this has no effect on the start that the first makeTree sees.
You'll somehow need each recursive makeTree to tell its caller how much of the string it consumed. Probably, the simplest way to do this is to change the return type to int; you can decide whether you want the function result to be the number of characters consumed, or the index where it stopped scanning, or something similar. Then, after calling makeTree recursively, use the function result to adjust the start parameter. Make sure makeTree returns the correct result, both in the leaf and the non-leaf cases. Be careful to avoid off-by-one errors.
You cannot create a tree just from preOrder list.
Atleast you need inorder traversal as well OR if is full tree then you can also use posrorder.

Traverse an array recursively

I'm trying to make a recursive method that receives an array and traverse it like with a loop, but without a loop.
Couldn't find a way to make an index, and increase each time I call the method.
If you have a function f(array,index) make it do something with array[index] and return function(array,index+1). Finally, to start it off call function(array,0). If there are any variables or state you are building up over the course of the recursive function, also pass it via the arguments.
A shot in the dark, but
public void printMyArray (String[] test, int index) {
// verify the index isn't too large
// Grab a value and do something with it.
}
Edit: As stated above, you basically just need to run through each value in the array. The easiest is really carrying over an index value (in my opinion).

Categories

Resources