I am wondering about the base condition in the recursive methods. in my lectures I see that my teacher some times write the base condition in various ways. See this please :
Here the base condition in the public method
public E find(E x) {
if (x == null) {
return null;
}
return find(root,x);
}
private E find(BinaryNode<E> n, E x) {
if (n.element.equals(x)) {
return n.element;
}
else if (x.compareTo(n.element) < 0) {
return find(n.left, x);
}
else {
return find(n.right, x);
}
}
is it OK if I write the base condition in the private method like this :
public E find(E x) {
return find(root,x);
}
private E find(BinaryNode<E> n, E x) {
if (n == null) {
return null;
}
else if (n.element.equals(x)) {
return n.element;
}
else if (x.compareTo(n.element) < 0) {
return find(n.left, x);
}
else {
return find(n.right, x);
}
}
Well, I would pick the following version:
public E find(E x) {
return find(root,x);
}
private E find(BinaryNode<E> n, E x) {
if (n == null) {
return null;
}
else if (n.element.equals(x)) {
return n.element;
}
else if (x.compareTo(n.element) < 0) {
return find(n.left, x);
}
else {
return find(n.right, x);
}
}
Why? Because it's correct. The other one isn't and would lead to the NullPointerException in case there is no such element in the tree.
The second question which appears in the OP post and the comment is whether to put the base condition in a public or a private method. The only possible correct answer is that each recursive method must have a base condition on which the recurrence will end.
public methods can be called by everyone so they should validate the input. They cannot assume that the parameters are valid. private methods can assume that parameters are ok and can focus on their logic.
The condition I would put in your public method would be:
public E find(E x) {
if (<x isn't valid - for example null and nulls are not allowed for values>) {
//do something here - exception or null
}
return find(root,x);
}
It would stand for making sure that the input for the private find...` would be correct. That's what you have to do.
Related
I'm working on Java Binary Search Tree, and I'm trying to use method findHelp() in find(). I'm expecting a return value of rt.getValue() (which is C2-112, as I print out right before return), but printing out findHelp() in help method returns null.
I couldn't find similar error online, so can someone help me figure out, or give a link to a similar issue?
Here is my code
private E findHelp(BinaryNode<Key, E> rt, Key k) {
int compare = k.compareTo(rt.getKey());
if (compare==0) {
System.out.println(rt.getValue()); // I'm getting C2-112 here
return rt.getValue(); // so I expect a return of C2-112
} else if (compare >0 ) {
if (rt.getRight() == null) {
return null;
} else {
findHelp(rt.getRight(), k);
}
} else {
if (rt.getLeft() == null) {
return null;
} else {
findHelp(rt.getLeft(), k);
}
}
return null;
} //
public E find(Key k) {
E tmp = findHelp(root, k);
System.out.println(tmp); // this prints null, not C2-112
return findHelp(root, k); // and so I return null
}
add a return before every findHelp(...)
I am posting here two functions. In the findPrime(int m, int i, int n) I have one outer if and outer else block from both the block I am getting return so it can be considered that the function is returning something I put same structure in endOther(String a, String b) i.e.
there are two main if-else blocks both are returning value as per function's return type so we can say that function is returning something but the endOther(String a, String b)
function is throwing compile time error saying that put return statement while first function is not throwing such error. I am not understanding this issue please help me. Type both the functions in eclipse and check
1.
static boolean findPrime(int m, int i, int n){
if(n == 0 || n == 1)
return false;
else {
if(i <= m) {
if(n%i == 0)
//if(m%i == 0)
return false;
else {
i++;
//return findPrime(m,i);
return findPrime(m,i,n);
}
}
else {
return true;
}
}
}
2.
public boolean endOther(String a, String b) {
if(a.length()==b.length()) {
if(a.equals(b))
return true;
else
return false;
}
else {
if(a.length()>b.length()) {
if(a.substring(a.length()-b.length(),b.length()).equals(b))
return true;
}
else {
if(b.substring(b.length()-a.length(),a.length()).equals(a))
return true;
else
return false;
}
}
}
Your endOther function must return a value on all possible execution paths. In case a.length() > b.length() the return may not be executed based on the condition of the inner if.
public boolean endOther(String a, String b) {
if(a.length()==b.length()) {
if(a.equals(b))
return true;
else
return false;
}
else {
if(a.length()>b.length()) {
// IF THIS FAILS THERE IS NO RETURN!
if(a.substring(a.length()-b.length(),b.length()).equals(b))
return true;
}
else {
if(b.substring(b.length()-a.length(),a.length()).equals(a))
return true;
else
return false;
}
}
}
As a general note, you could use some of the methods in String to improve your code, e.g. String.endsWith instead of the substring operation. This would be more readable. a and b being identical is a special case of String.endsWith, so the following should be equivalent:
public boolean endOther(String a, String b) {
return a.endsWith(b) || b.endsWith(a);
}
I was reading about recursive methods in java ... I do not undserstand the base condition of the recursive method ... Here are two examples
public int weight() {
return weight(root);
}
/ * Returns the weight of the tree where n is the root. * /
private int weight(Node n) {
if (n == null) {
return 0;
} else if (n.left == null) { // då är n.right också null
return n.data;
} else {
return weight(n.left) + weight(n.right);
}
}
public boolean isMobile() {
if (root == null) {
return true;
} else {
return isMobile(root);
}
}
/ * Returns true if the tree where n is the root of a mobile. * /
private boolean isMobile(Node n) {
if (n.left == null) { // då är n.right också null
return true;
} else {
return isMobile(n.left) && isMobile(n.right) &&
weight(n.left) == weight(n.right);
}
}
My wonder : in the weight() method why do not we do like this :
public int weight() {
if (root == null) {
return 0;
} else {
return weight(root);
}
}
As you can see the base condition in the isMobile() method is directly under it but the base condition in the weight() method is under the private method ..
When it is possible to write the base condition of the recursive directly under it or in a separate private method ?
Thanks
EDIT :
public int weight() {
if (root == null) {
return 0;
} else {
return weight(root);
}
}
private int weight(Node n) {
if (n == null) {
return 0;
} else if (n.left == null) { // då är n.right också null
return n.data;
} else {
return weight(n.left) + weight(n.right);
}
}
in the weight() method why do not we do like this : [...]
The simple answer is because parameterless weight() overload of the method is not recursive, even though it relies on a recursive implementation that takes Node as its parameter. The base condition must be in the recursive method itself, because that is where the decision to stop calling itself must be made.
Despite being overloads of the same name, your two weight methods work together like this:
public int nonRecursiveWeight() {
return recursiveWeight(root);
}
private int recursiveWeight(Node n) {
...
}
The nonRecursiveWeight provides a nice public "front" for the recursive implementation recursiveWeight, hiding the node from the API users.
isMobile pair of methods follows the same arrangement: you have a recursive implementation, and a non-recursive "front" sharing the same name.
Base condition must be in the recursive method. The method weight() is not recursive as it is not calling itself. It is calling a recursive method weight(Node n) which has and must have base condition.
if (n == null) { return 0; }
Intention in the isMobile() and isMobile(Node n) is a bit different. The author probably wanted to check for root == null directly in isMobile() method to avoid double checks in recursive method but they can be rewritten like this:
public boolean isMobile() {
return isMobile(root);
}
private boolean isMobile(Node n) {
if ( n == null || n.left == null ) return true;
return isMobile(n.left) && isMobile(n.right) && weight(n.left) == weight(n.right);
}
Again isMobile(Node n) is recursive and isMobile() is not. The isMobile methods now look the same as weight methods. In general the rule is that the recursive methods are the ones which call themselves and they must have base condition which will terminate recursion.
Also please note that you do not need to write else if you have a return before that. For example:
boolean someMethod() {
if ( something ) {
return true;
} else {
return false;
}
}
Can be rewritten as:
boolean someMethod() {
if ( something ) {
// ...
return true;
}
// if something was true then the next piece of code will never get executed
// if was not true then the next piece of code will always execute
// ...
return false;
}
You probably meant if (root == null) in your re-write.
You still have to check in weight(Node) since it's recursive–why do it twice?
I'm new to recursion and I don't see why this function won't compile. It is apparently missing a return statement. From testing it also seems as though my return statements do not return?
// recursive search method
public BinaryTree<T> recursiveSearch(BinaryTree<T> t, T key) {
if (key.compareTo(t.getData()) < 0) {
if (t.getLeft() != null) {
recursiveSearch(t.getLeft(), key);
} else {
return null;
}
} else if (key.compareTo(t.getData()) > 0) {
if (t.getRight() != null) {
recursiveSearch(t.getRight(), key);
} else {
return null;
}
} else if (key.compareTo(t.getData()) == 0) { // key is found
return t;
} else { // not in binary tree
return null;
}
}
The problem is on the lines inside the if branches that make recursive calls.
Your code will behave correctly when it reaches any of your else branches, because all of them have return null. If code takes one of the if branches, however, the control would reach the end of your method without hitting a return. The fix is simple - add the missing returns:
return recursiveSearch(t.getRight(), key);
Yes, it is missing a return statement for the recursion statements.
public BinaryTree<T> recursiveSearch(BinaryTree<T> t, T key)
{
if (key.compareTo(t.getData())<0){
if (t.getLeft() != null) {
recursiveSearch(t.getLeft(), key); // This case doesn't return anything
} else { return null;}
} else if (key.compareTo(t.getData())>0) {
if (t.getRight() != null) {
recursiveSearch(t.getRight(), key); // This case doesn't return anything
} else {return null;}
} else if (key.compareTo(t.getData())==0){ // key is found
return t;
} else {
//not in binary tree
return null;
}
}
I dont know your program logic, but if I have to guess, you might wanna add a return statement to the recursive calls. Like so,
return recursiveSearch(t.getLeft(), key);
and
return recursiveSearch(t.getRight(), key);
I have a method which returns the value of my POJO.
My POJO class's name is Tail.
public Tail getTail(long value1, String value2, int value3) {
List<Tail> l = /*I get this list via Hibernate. */
if (l.size() == 1) {
return (Tail) l.get(0);
}
else if (l.size() > 1) {
for (Tail t : l) {
First ik = minorDAO.getFirst(value3, t.getNumber());
if( ik.getCond().equals("I") ){
t.setCond("I");
continue;
} else {
return t; //???????????????
}
}
} else {
return null;
}
}
In the else statement inside of the foreach loop where the question mark comment is I want to return t, but if I do this, I get an error stating:
"This method must return a result of type Tail".
How can I return the value there?
with that code you dont get the message:
public Tail getTail(long value1, String value2, int value3) {
List<Tail> l = --> (I get list via Hibernate.)
if (l.size() == 1) {
return (Tail) l.get(0);
} else if (l.size()>1){
for (Tail t: l) {
First ik = minorDAO.getFirst(value3, t.getNumber());
if( ik.getCond().equals("I") ){
t.setCond("I");
continue;
} else {
return t;
}
}
}
return null;
}
If the method has to return Tail you must deliver it in any possible case.
For example:
if each element is true in this case:
if( ik.getCond().equals("I") ){
there would be no return. You iterate about the whole list and nothing happens...