0

Ok, so i have to create a recursive method for counting the nodes in a tree, and i did this (variable names are in portuguese, sorry):

public int contaNos(Arvbin r) {
        Integer cardinalidade = 0;
        contaNosPrivado(r, cardinalidade);
        return cardinalidade;
}
private void contaNosPrivado(Arvbin r, Integer cardinalidade) {
        if (r==null) {
            return;
        }
        cardinalidade=cardinalidade+1;
        contaNosPrivado(r.esq, cardinalidade);
        contaNosPrivado(r.dir, cardinalidade);
        return;
}

Arvbin is the binary tree, esq and dir are the left and right references to the tree's branches.

I thought this would work, but for some reason when i try to run it, it returns 0. I've usen a little bit of debugging and i think the issue is that when the methods finish and come back to the original non-recursive one, the cardinalidade variable is set to 0. I'm not sure if it's because autoboxing is messing with my Integer and turning it into an int, and then when i call the method it passes a copy of the value instead of the reference to the existing object, and i don't know how to fix it. If anyone could help, i'd greatly appreciate it

  • Welcome to SO. **"variable names are in portuguese, sorry"** please refactor to English to make your code more readable. See SO [policy](https://stackoverflow.blog/2009/07/23/non-english-question-policy/) : **"insisting on posting a question in another language is no different than the “do my work for me” sort of programming questions — the worst possible sin on SO"** – c0der May 20 '18 at 03:19

2 Answers2

1

The problem is that wrapper classes are immutable in Java. cardinalidade is just a parameter of contaNosPrivado here and, unfortunately, cannot act as an argument like other object type parameters can, i.e. this local reference cannot change inner fields of the object that initial reference refers. Any change to it affects it only the way it affects any primitive local variable.

What exactly happens inside your contaNosPrivado:

  1. On invocation, it is indeed supplied a reference to an Integer object. This reference is assigned to a local variable named cardinalidade.
  2. In this line:

    cardinalidade=cardinalidade+1;
    

    this object is first unboxed to a primitive int variable, this variable is incremented afterwards, and finally the result is reboxed into a new Integer object which is then assigned to cardinalidade. There is no way to 'increment' original object, even if you use the increment operator:

    cardinalidade++;
    
  3. Any further processing applies to the newly created Integer object and doesn't affect the reference passed to contaNosPrivado.

To achieve your goals, use something like this instead:

static int contaNosPrivado(Arvbin r) {
    if (r == null)
        return 1;
    else
        return contaNosPrivado(r.esc) + contaNosPrivado(r.dir);
}
John McClane
  • 3,218
  • 2
  • 9
  • 27
0

As @John McClane has pointed out, you can't pass an Integer argument by reference, only by value.

But there's also no need for a private helper method, you can just simplify it all to a single method:

public int countLeaves( BinaryTreeNode n )
{
    return n == null? 0 : ( countLeaves( n.rightLeaf ) + countLeaves( n.leftLeaf ) );
}

Or (excuse my poor Portugese):

public int contaNos( Arvbin r )
{
    return r == null? 0 : ( contaNos( r.esq ) + contaNos( r.dir ) );
}
Richard Inglis
  • 5,509
  • 2
  • 29
  • 36