Merging methods (Binary Search Tree) - java

I'm working on writing a BST (Binary Search Tree) and there's an example in a book I'm reading that gives this code
public int height() {
return height(root);
}
private int height(BinaryNode<E> node) {
if (node == null) {
return 0;
} else {
int leftHeight = height(node.left);
int rightHeight = height(node.right);
if (leftHeight < rightHeight) {
return 1 + rightHeight;
} else {
return 1 + leftHeight;
}
}
}
but there's no explanatory information about why there's two separate height methods.
Therefore I'm asking you guys if it's possible to merge these two methods in to one height method. Is it possible, if not. Why not?
Appreciative for any help possible,
Bob.

It's an example of method overloading.
There are two methods with the same name, that differs by the number of type of arguments passed.
The first method has no parameter, the second one has one parameter of type BinaryNode<E>.
When the first method is called, it calls the second one passing to it the root variable (which I assume is of type BinaryNode<E>).
The first one is also public, so you can call it from other classes, the second one is private and is callable only from the class where it is defined.

Assuming that the methods you provided are part of the tree class, then I don't see how you can merge them. The first is a public method, which expects no argument, and the second is a helper recursive method that checks the height of a given node. The first one uses the second: it invokes the helper method on the root itself. The second method shouldn't be visible from outside, so it's private.
If the height method was implemented on the Node level, then it could be done in a single recursive method with no arguments.

Notice that the int height() method is public. This is the one that will be called from outside your class. It must decide the height of the tree. It will do this by calling the other one.
See also that the int height(BinaryNode<E> node) is private because it is used only by the public int height() method to determine the height of any subtree.

Related

Return statement in Helper Method(Java)

I am practicing simple coding problems from codingbat. One of the problems are asking me to use helper method to prevent redundant codes. However, I am very lost because I do not know why I should use public and int as return type for this problem.(because the question asks me to use header below)
public int fixTeen(int n)
What does the return from the helper method doing? Also, how do I know if I should use private or public for my helper method?
Please take a look at my code.
// Given 3 int values, a b c, return their sum. However, if any of the values
// is a teen -- in the range 13..19 inclusive -- then that value counts as 0,
// except 15 and 16 do not count as a teens. Write a separate helper
// "public int fixTeen(int n) {"that takes in an int value and returns that value
// fixed for the teen rule. In this way, you avoid repeating the teen code 3
// times (i.e. "decomposition"). Define the helper below and at the same
// indent level as the main noTeenSum().
public int noTeenSum(int a, int b, int c) {
return fixTeen(a) + fixTeen(b) + fixTeen(c);
}
public int fixTeen(int n) {
if (n >= 13 && n <= 19 && n != 15 && n != 16)
n = 0;
return n;
}
Edit:
What is the difference between setting return type void and int for the helper method? At first, I thought return int is unnecessary and tried to set the return type as void but it gave me an error.
In general, at least for the beginnings of java, methods should be named public. Later on, when you get to object oriented programming, the area it's in (public or private) matters more. For example, adding the keyword "public" means that that value can be accessed outside of the class, while "private" means it cannot. This is important for when you don't want the end user to be able to access your private data.
Point is, when you make a method, for now have them set to public.
Next up is the helper method. After the "public" or "private", you have the return type. You have it set to "int". Therefore, the return type must be an integer. It can't be a string, or a double - it must be an integer. If you set the return value to "void", then there would be no return value, and if you tried to write "return(n);", it would give you an error.
So TLDR: It's named "public" because you want to be able to access this method outside of the class, and it says "int", because you need to return an integer type. Then, when you return(n), it'll give the value, say, a == 7, and if b == 18, it'll set b == 0. After that, it adds the numbers together, and you have your answer!

Confusing behaviour of overloading

I am experiencing a behaviour that I do not understand related to this code snippet. More precisely, I was expecting the call of getUniqueCost method for the case in which the operator is of type Projection (that is, when n.isProjection() is true) to be calling the method having as signature private double getUniqueCost(final Projection p) instead of that having signature private double getUniqueCost(final Node p).
Note that Projection is a subclass of Node.
Here the code for the two aforementioned methods:
private double getUniqueCost(final Node n){
if(n.isScan())
return getUniqueCost(estimateCardinality(n));
if(n.isJoin())
return getUniqueCost((NJoin) n);
if(n.isUnion())
return getUniqueCost((Union) n);
if(n.isMaterialization())
return getUniqueCost(n.getChildren().iterator().next());
if(n.isProjection()){
return getUniqueCost(child.isJoin() ?
n.getChildren().iterator().next() : ((Projection) n));
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
private double getUniqueCost(final Projection p){
return getUniqueCost(estimateCardinality(p)) +
getUniqueCost(p.getChildren().iterator().next());
}
The only way to actually manage to call the second method was to modify the first method as follows (the omitted code is the same as before):
private double getUniqueCost(final Node n){
[...]
if(n.isProjection()){
final Node child = n.getChildren().iterator().next();
if(child.isJoin()){
return getUniqueCost(child);
}
final Projection proj = (Projection) n;
return getUniqueCost(proj);
}
throw new IllegalArgumentException("Unknown node type: " + n.getOperator());
}
Given that the cast is executed before actually calling the method (that is, call by value semantics, where the parameters are evaluated before evaluating the method itself), I was expecting it to be sufficient to call the most specific method (the one accepting a parameter of type Projection).
It has been a while since I had a look at the type system of Java, my suspect is that the whole expression child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n) is typed as Node, due to the left part those type is indeed Node.
Does anybody can confirm it? If no, do you have a better understanding of what's going on here?
In addition, is there a way to have a more compact (elegant?) way of writing the second version of the code?
The type of your ternary conditional expression - child.isJoin() ? n.getChildren().iterator().next() : ((Projection) n) - is a type that both n.getChildren().iterator().next() and ((Projection) n) can be assigned to. Therefore, if one of them is Node and the other Projection, assuming Projection is a sub-class of Node, the type of the expression is Node.
Your second snippet can be shortened a bit :
if(child.isJoin()){
return getUniqueCost(child);
} else {
return getUniqueCost((Projection) n);
}
Casting n to Projection is enough the get the overloaded getUniqueCost(final Projection p) method called. You don't need an intermediate variable.

What is returning class when use "return this"?

I started learning Java and I couldn't understand one of examples in "Thinking in Java" book.
In this example author represent, as he state "simple use of 'this' keyword":
//Leaf.java
//simple use of the "this" keyword
public class Leaf {
int i = 0;
Leaf increment() {
i++;
return this;
}
void print() {
System.out.println("i = " + i);
}
public static void main(String[] args) {
Leaf x = new Leaf();
x.increment().increment().increment().print();
}
}
And when above code is working as indeed, I cant understand what increment() method is returning.
It's not variable i, it's not object x? I just don't get it. I tried to modify program to understand it (like replace return this with return i or print x instead of i), but compiler shows me errors.
return this;
will return the current object i.e. the object which you used to call that method. In your case object x of type Leaf will be returned.
this represents the instance of the class from which the method was called. So returning this means returning this instance of the class. So, as the return type shows anyway, the increment() method is returning a Leaf and its returning the instance in which the increment() method was called.
This is why you can call:
x.increment().increment().increment().print();
Because with each call to .increment() you are getting another Leaf on which you can call all the methods inside Leaf again.
this is a keyword that is referencing the current Leaf instance. When you create your first Leaf with Leaf leaf = new Leaf () it creates a singular instance of Leaf
Esentially, you are returning the Leaf instance that is calling increment()
return this; returns the instance of the class it is acting on. So every call of increment() is returns the same instance and then it calls increment again. You can keep on calling increment() as :
x.increment().increment().increment().increment().increment().increment()...

What should I use as the return statement?

I am creating a method called swapElements(). It takes an array of integers, and two integer indexes. The method should swap the values of the array elements with the specified indexes.
public class{
int swapElements(int[] number, int value1, int value2){
int temp = number[value1];
number[value1] = number[value2];
number[value2] = temp;
}
}
As you have presented it, this method does not need to return anything, and should probably be declared void. However, if there is a specific contract it needs to fulfill then you should return whatever the interface definition says it should return.
There are four things wrong with your code.
The thing you're asking about: use return number;, because you want to return the array with swapped elements.
Make the method return an int[] (like int[] swapElements), not an int.
Your class has no name. You need to add a name, like public class IntArraySwapper { ....
Your method should be static. Without using that keyword, you must call it on an instance, like new IntArraySwapper().swapElements(...). Since this method has nothing to do with class instances, simply make it static (static int[] swapElements) so that you can call it like IntArraySwapper.swapElements(...).
Note that the method will also modify the original array, so techinically you don't need to return anything. If you want, you could just make it a void method and use the old array.
you can just make it return void.
or maybe a boolean to indicate that the sawp happened, with no errors.
like index out of range error.
In such cases the return type is not strictly required. So, you should return void. But if you indeed want to return something, consider returning boolean to specify if the swap happened or not. More precisely you can include the swap code into try catch block which returns True if the swap happened without any error and False otherwise.

Logic Explanation behind this code- Java

I have this code written by someone else and I am having hard time to understand it.
It is working fine and generates correct result but I couldn't understand how it works
package you;
import clowns.Clown;
import clowns.Volkswagen;
public class You {
static int counter = 0;
static Volkswagen vw = new Volkswagen();
public static void main(String args[]) {
vw.add(new RecursiveClown());
vw.done();
}
static class RecursiveClown extends Clown {
public int hashCode() {
if (++counter < 20) {
vw.add(new RecursiveClown());
}
return super.hashCode();
}
}
}
couldn't understand that apparently RecursiveClown is not being called anywhere neither its hashcode() function
then how come it works and add RecursiveClown object.
also why it is returning super.hashCode();
there is this other class, that was referenced in above code.
package clowns;
import java.util.HashSet;
import java.util.Set;
public class Volkswagen {
private static final int CAPACITY = 5;
private Set<Clown> clowns = new HashSet<Clown>();
public synchronized void add(Clown clown) {
if (clowns.size() >= CAPACITY) {
throw new IllegalStateException("I'm full");
} else {
clowns.add(clown);
}
}
public synchronized void done() {
if (clowns.size() == 20) {
// The goal is to reach this line
System.out.println("I'm a Volkswagen with 20 clowns!");
}
}
}
output of these two classes are: I'm a Volkswagen with 20 clowns!
but whenever I printed
clowns.size()
in add() method of 'Volkswagen' it always return 0 then How come it compares
clowns.size() == 20
and evaluates it as true?
The explanation why your Volkswagen contains more clowns than its capacity allows is because of the way the clowns are added.
It is essentially within the line
clowns.add(clown);
in method Volkswagen.add(). It first calls hashCode of the clown to be added and then adds it to its internal structure. Since hashCode recursively calls Volkswagen.add() again, at this point the clown was not yet added to the (internal data structure backing) HashSet, thus size() returns 0.
This way the capacity is not reached at the begin of method Volkswagen.add(), but only when exiting this method (because only then clowns are actually added to the HashSet).
The Set<Clowns> is an HashSet, which is itself backed up by a HashMap.
So, basically, when you add an object to the Set<Clowns>, it will invoke HashMap.put().
HashMap.put() call the hashCode() method of the provided object.
That's why your object's hashCode() method is invoked without explicit call.
The function HashSet.add will, as fge mentioned, check the hashcode of the object, before it is added, which means that before clown #1 is added, the Volkswagan.add function for clown #2 is called.
This follows until there is a 20 deep recursion in the hashcode function, and once that terminates all 20 clowns are added at one go.
The code relies on HashSet relying itself on .hashCode().
When an element is inserted into a HashSet, this implementation of Set determines the uniqueness of the element by first calling .hashCode() on the element to add; if and only if the hash code equals another one is .equals() considered.
It returns super.hashCode() because this is Object's one: Clown does not override it.
Since RecursiveClown extends Clown, it is possible to add it to a Set of Clowns. When adding one, .hashCode() adds another recursive clown to the Volkswagen, until counter reaches 20.

Categories