Difference of two functions - java

I have one question regarding recursive functions and updating function parameters. Namely, I have two functions:
public static void populateArray(int[]level,Node root,int currentLevel) {
currentLevel++;
if(root.left!=null) {
populateArray(level,root.left,currentLevel);
}
level[currentLevel]++;
if(root.right!=null) {
populateArray(level,root.right,currentLevel);
}
}
public static void populateArray2(int[]level,Node root,int currentLevel) {
if(root.left!=null) {
currentLevel++;
populateArray2(level,root.left,currentLevel);
}
level[currentLevel]++;
if(root.right!=null) {
currentLevel++;
populateArray2(level,root.right,currentLevel);
}
}
These functions should fill an empty array with number of nodes in binary tree at each level. I thought that these functions work the same way, but it turns out that first function does that task correctly, and the second one doesn't, that is, currentLevel is not updated after returning from recursive call in the second function, and I am curious why is this the case?
I thought that in both functions, when we return from recursive call, parameter will be automatically updated (what is the case with the first function).
Second function will only work if after each recursive call we place currentLevel-- .. Does someone maybe know why this happens? Thank you in advance!

In the populateArray2 you're first accessing the level[currentLevel]++ and only then increase the currentLevel by 1 if the root.right != null.
I've added some comments to your code to highlight the difference:
public static void populateArray(int[]level,Node root,int currentLevel) {
currentLevel++; // Increase currentLevel by 1 first
if(root.left!=null) {
populateArray(level,root.left,currentLevel);
}
level[currentLevel]++; // Increase level by 1 after that
if(root.right!=null) {
populateArray(level,root.right,currentLevel);
}
}
public static void populateArray2(int[]level,Node root,int currentLevel) {
if(root.left!=null) {
currentLevel++;
populateArray2(level,root.left,currentLevel);
}
level[currentLevel]++; // Increase level by 1 first
if(root.right!=null) {
currentLevel++; // Increase currentLevel by 1 after that
populateArray2(level,root.right,currentLevel);
}
}
So that's the key difference here, causing different results because different levels are increased.
In addition, if both the root.left and root.right aren't null, you've done currentLevel++ twice in your populateArray2 method as well.
I'm not sure what you were trying to accomplish with populateArray2, but I would just remove it and stick with your original populateArray-method..
EDIT: As mentioned by #Simon, I've only addressed the difference between the two populateArray methods as was the question of OP. I haven't mentioned an actual fix for his requirements.
See #Simon's answer below for an actual fix following those requirements.

Your second function doesn't work properly because you are incrementing twice if the Node has both LEFT and RIGHT elements .
Hence u need currentElement-- at the end

Related

Recursion: How to avoid returning before all paths are completed

This can apply to any language really but I'm using Java. This seems so simple but I been programming many hours straight now and my brain is fried and I'm just missing something simple I think. See example below. In the populateArray() method below, there is a return call (see the comment) but will that cause the parent method to return prematurely (before all recursion is completed and the mListUrls is fully populated) ?
public ArrayList<String> startMethod( String s){
mString = s;
Node startNode = getNode(mString );
populateArray(startNode, 0 );
return mListValues;
}
private void populateArray(Node node, int i{
if(i == 100 ){
mListValues.add(node.value);
//I do want to continue here, but will returning here return the startMethod() above prematurely,
//before all recursion is completed?
return;
}
if(node.first() != null){
populateArray(node.first(), i + 1);
}
if(node.second() != null){
populateArray(node.second(), i + 1);
}
if(node.third() != null){
populateArray(node.third(), i + 1);
}
}
The recursion comes into play when populateArray calls itself, populateArray. When any call returns, it only returns to its parent which may be populateArray, or some other function. Think of a stack of calls, any return only pops the top off. It doesn't return ALL the way back to the base. The parent can decide what do do then. It can decide any number of things, call something else, recurse again, or return to its parent (the grandparent), which could very well cascade all the way to the root, but not necessarily.

Java recursive method difference

What is the difference between the following two methods:
public boolean recursionMethodOne(Node n) {
System.out.println(n.getValue());
return recursionMethodOne(n.next());
}
public void recursionMethodTwo(Node n) {
System.out.println(n.getValue());
recursionMethodTwo(n.next());
}
Which one do you use for recursion and what is the difference?
Thanks
Both your codes doesn't exits. You need to add a return for a test condition. For example:
public void recursionMethodTwo(Node n) {
if (n == null) {
// Standard way to exit a void function without executing remaing code
// note that return null; doesn't compile
return;
}
System.out.println(n.getValue());
recursionMethodTwo(n.next());
}
Returning a value or not depends on the kind of function.
For example if you need to calculate a factorial you need a result, if you need to print a list you don't.
So for your example seems that the method two is most closer to your needs.
Otherwise you need to ask yourself what is the returning boolean value of the function? If you have a nice answer to this question you can implement the code returning a value.

contains(int aData) with Recursion Linked List Java

I am having problems trying to check if a value is in a linked list or not using recursion. The values in the linked list are between 0 and 5. If the value is in the linked list, the method should return true. However, I am getting wild answers across the board if the value is indeed in the linked list. Some numbers will return false, and some will return true. I am not sure why it is doing this. Thanks!
public boolean contains(int aData)
{
Node currentNode = firstNode;
if(currentNode == null) {
return false;
}
if(currentNode.data == aData) {
return true;
}
else {
return false;
}
}
You're only checking one node (the first node). You're going to be needing something like this:
public boolean contains(int aData, Node node)
{
Node currentNode = node;
// base case; if this node is null, return false
if(currentNode == null) {
return false;
}
// if this node contains the data, return true, otherwise, check next nodes.
if(currentNode.data == aData) {
return true;
} else {
return contains(aData, currentNode.next);
}
}
You can call the above function starting with the head node
contains(5, headNode);
and it will run through your entire list until either a) it finds the data, or b) it has exhausted all options and the data was not found.
As has been mentioned, you are not using recursion and are only checking the first Node. If you want to use recursion, you'll need to call the contains method from within the contains method, which you are not currently doing. Even if you were to simply call it at the end of the method as it stands now, it still wouldn't do anything - think about how you might rewrite it if the method started:
public boolean contains(int aData, Node nodeToCheck)
Recursion has a very well defined form that is used in almost all cases. Essentially the form is:
type method(context) {
if (one of the base cases holds)
return appropriate base value
else
for each possible simpler context
return method(simpler context);
}
This works by progressively breaking the problem down into smaller pieces until the problem is so simple it has an obvious answer (i.e. the base case). The key to using recursion is to ask yourself 'in what situations is the answer obvious?' (i.e. the base cases) and 'when the answer isn't obvious how can I simplify the situation to make it more obvious?'. Don't start coding until you can answer those questions!
In your case you have 2 base cases: you've reached the end of your list or you have found the value. If neither of those cases hold then try again in a simpler context. In your case there's only one simpler context: a shorter list.
Putting all that together you have:
public boolean contains(Node node, int data) {
if (node == null)
return false;
else if (node.value == data)
return true;
else
return contains(node.next, data);
}

Return the number of elements in a linked list recursively

I have the following recursive method in a class called ImageNode which is passed the head(this - the start of the linked list) from a class called Image.
I thought my code would recursively go through each node, increase the count then when its at the end return the count, unfortunatly not. Where am I going wrong?
private int countRec() {
int count = 1;
ImageNode node = this;
if (node.next != null ){
node = node.next;
count++;
countRec();
}
return count;
}
You're ignoring the result of countRec() - and you're iterating within the recursive call, defeating the purpose. (You're also making a recursive call on the same object, with no parameters and no change in state... so that can't do any good.) My recursive approach would be based on a design of:
If the next node is null, then the size of the list is 1
Otherwise, the size is 1 + the size from the next node onwards.
So:
private int countRec() {
return next == null ? 1 : 1 + next.countRec();
}
Now that doesn't allow for a list of length 0 of course... you probably want to separate the idea of the list from the node, in which case the list class would have something like:
public int count() {
return head == null ? 0 : head.countRec();
}
where the value of head is a reference to the head node if there is one, or null otherwise.
Of course, this will be O(n) in time and space. You can get O(1) space using iteration instead of recursion, and O(1) time by just keeping the size of the list as an instance variable in the list, updating it when you need to. I'm hoping that this question was based on an educational requirement rather than real code though - in production code, you'd just use the collections provided already.
The definition of a recursive function is it is defined in terms of itself: i.e. the count of elements in a list is equal to 0 if an empty list; otherwise it is equal to 1 + the count of the rest of the elements of the list.
The italicized portion of the above definition is where the function call gets made.
private int countRec(ImageNode node) {
if (node == null) {
return 0;
} else {
return 1 + countRec(node);
}
}
A recursive function is useful when it uses the result of the further calls to solve his problem (like an inductive step on mathematics). Your function are not using the return for the countRec() call for anything, and you're still trying to solve the issue without the recursion help. You can solve it by using it, as:
if(node.next != null)
{
node = node.next;
count = countRec()+1;
}
return count;
Of course, since we're telling about getting your code better, you wouldn't even need to use this node var, just doing:
private int countRec() {
if (this.next != null )
return (this.next.countRec())+1;
return 1;
}
Hope that helps.

Unable to understand why count is not getting incremented

As a part of exercise, i am writing a recursive code to count the number of nodes in a queue. The code part which I have added/modified (in NodeQueue.java) is here:
public class NodeQueue implements Queue
{
static protected int count; //for RecNodeCount method only
protected Node beingCountedNode = head; //for RecNodeCount method only
// other methods..
public int RecNodeCount()
{
if(beingCountedNode == null)
return count;
else
{
count++;
beingCountedNode = beingCountedNode.getNext();
return RecNodeCount();
}
}
The entire code is as here:
Queue.java: http://pastebin.com/raw.php?i=Dpkd8ynk
Node.java: http://pastebin.com/raw.php?i=Zy0KbrtJ
NodeQueue.java: http://pastebin.com/raw.php?i=j6hieiLG
SimpleQueue.java: http://pastebin.com/raw.php?i=vaTy41z4
I am unable to understand why I am getting zero even after enqueueing few nodes in the queue. The size variable returns the correct number. I am doing more or less the same with the count variable (I think!) i.e. incrementing the required variable.
Although I believe the method will work (if beingCountedNode is set properly before the call. See #peter.petrov answer), it is weird to use instance variables as parameters for a function. I think the recursive function should have the signature int Count( Node node ) which returns the number of nodes after (including) the given Node.
// returns the number of nodes in the list
public int Count(){ return CountHelper( head ); }
// helper recursive function
// returns the number of nodes in the list after and including "node".
// call with head of the list to get the count of all nodes.
private int CountHelper( Node node )
{
if( node == null )
return 0;
else
return 1 + CountHelper( node.getNext() );
}
Also note in your current example, you never reset count, so if I call RecNodeCount() twice in a row, your method will tell me the count is twice what it actually is. Edit, actually I guess it wouldn't since beingCountedNode would be null, but it is still weird to do it this way.
My guess is this following.
When this line is executed
protected Node beingCountedNode = head;
your head is null.
So beingCountedNode is set to null. Due to this,
later in your method you never enter the else clause.
Just add a few System.out.println calls in RecNodeCount()
and you'll see what exactly is happening in this method.
Maybe this is not a direct answer for your issue, but why do you even use recursive and static variable here? Is' really easy to count nodes with simple while.
public int nodeCount(Node node) {
int result = 0;
while(node != null) {
node = node.getNext();
result++;
}
return result;
}

Categories

Resources