can anybody help me to trace this piece of code if its correct or incorrect.i am studying recursion these days.
boolean search(Element element) {
Element c=first;
if(c==null)
return false;
else if(element.asset < c.asset)
if(c.left==null)
return false;
else
return search(c.left);
else if(element.data>c.data)
if(c.right==null)
return false;
else
return search(c.right);
else
return element.asset==c.asset;
}
it lacks stop condition. you should check if t.left == null, or you will get NullPointerException. also, you should return t.left.isExist(..) OR t.right.isExist(...) and not isExist [you will want to invoke this method on the son]
currently, this version will get into infinite loop - because you will always check in the same root node.
Your code isn't symmetric.
for one side, you call isExist(t.left), for another you call isExist(a.right)
You probably want to call t.left.isExist(a) and t.right.isExist(a), but that is purely speculative as you do not have a complete SSCCE for us to look at.
It is syntactically correct Java. But I don't see how it could possibly be doing what you intend.
It appears that the 'element' parameter is the thing you are searching for and the 'first' field in the current class is the root of the binary tree.
It's unclear if the key for the binary tree and search (in the Element class) is 'asset' or 'data'. The 'less than' test uses 'asset', while the 'greater than' test uses 'data'. It seems likely that both lines should use the same field. It might be that one of these two fields ('asset' or 'data') should not be referenced in this method at all. Maybe the last line of the method should be just 'return true;'?
(I suspect that the "stop condition" and the "code isn't symmetric" answers above are both incorrect. But I could be wrong: It's hard to tell with only the code given.)
I agree that infinite looping is likely: I suspect that you need to create a second 'search' function that accepts two 'Element' parameters -- one being the thing to search for (like the current 'element' parameter) and the other being the next Element to search -- the equivalent of current local variable 'c'. I would do the "Extract Method" refactoring on everything in the body of the current 'search' method except the first line, and then change the two recursive calls to use the new method.
(Some of this is speculative, based on me guessing what you want or intend, given limited information. So I could, of course, be quite wrong.)
Related
What is the preferred design for methods that encounter predictable but unpreventable failure? Should they return an empty result or throw an exception on failure? Please explain your reasoning.
I'll give two sample methods:
A method like Arrays.binarySearch() that returns the index of a value within an array.
Tickets.buy(20, 100). A ticket bot attempts to buy at least 20 tickets using $100. The method returns the list of tickets that were bought.
For both methods, let us assume that the user has no way of predicting whether the method will succeed in finding a match.
Method 1 can fail if:
The array does not contain the desired value.
Method 2 can fail if:
There aren't enough tickets.
There are enough tickets for sale, but they cost more than $100.
Java chose to return the equivalent to an empty result for method 1, but doing the same for method 2 wouldn't allow you to differentiate between the two kinds of errors. What are the guidelines for choosing between the two possible designs?
Please note that although this question contains two concrete methods, I am looking for general design guidelines not a specific solution to the aforementioned methods.
The best approach depends on the case.
Case 1:
Since the method returns the index of the found element, I suggest returning -1 if the desired value has not been found. Stick to the well known API of almost everyone is familiar with, like for indexOf().
Case 2:
Here I would suggest using exceptions (InsufficientMoneyException, OutOfTicketsException, ...). An empty list or null is not very meaningful and the different error cases cannot be reflected with that.
This way you can properly handle the exceptions in their respective catch blocks.
In general you have to keep in mind that throwing exceptions is expensive operations, because the stack trace has to be built.
This question is rather opinion-based, just like the whole returning null/throwing an exception/returning empty object dilemma.
I personally think that returning -1 is for the first method and throwing exceptions for your second method would be better.
Following the single responsibility principle, one method should do one thing.
The goal of the first method is to search for an element, it can either find it or not find it. This is the expected behavior.
The goal of the second method is to buy a ticket. Unlike the first method, it's not checking if it can buy a ticket or not, it's doing it. The expected behavior is that the ticket is bought. If that behavior does not happen, something went wrong, thus an exception should be thrown.
I also think that #StriplingWarrior's approach might not be ideal because if you have more than just two possible cases, you can't really have Either<A, B, C, D, E, ...>.
RIP. I spent 15 minutes writing an answer and I accidentally opened the web console and deleted the body. The last saved answer was like 10 minutes before. I don't even know how you can accidentally do that. I guess F12 and DEL are kinda close
Typically you'd want to make your return type be an object that contains all the information you're likely to need to know.
In the early days of Java, it was common to return normally invalid values like -1 (in the case of Arrays.binarySearch()) or null in order to represent the absence of a value. More modern APIs tend to return an Optional<> to provide compile-time enforcement of the concept that there may not be a result (as well as differentiating between "no result" and "the result is null).
In the Tickets.buy() example, you could have an Either<String, List<Ticket>>, where the "left" value can be a reason that the purchase failed, and the "right" value can be the tickets that got purchased if it succeeded.
I ended up taking the advice found at https://stackoverflow.com/a/77361/14731
My interpretation is as follows:
From a purist perspective, if the purpose of Arrays.binarySearch() is to return the index of an element in an array, then it should throw an exception when no match is found. The fact that no result has a negative index is a convenient fact that allows us to return -1 instead. But again, in an ideal world this method should be throwing an exception. If this method was answering the question "does the array contain this element" and returning a boolean then no exception would need to be thrown.
Tickets.buy(20, 100) assumes that a match will be found in purchase the tickets. If no match is found then an exception should be thrown.
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.
As part of my AP curriculum I am learning java and while working on a project I wondered which of the following is best way to return a value?
public double getQuarters(){
return quarters;
}
or
public void getQuarters(){
System.out.println(quarters);
}
***Note: I now that the second option is not "technically" returning a value but its still showing my the value so why bother?
Your answer would be correct. The second method doesn't return any value at all, so while you might be able to see the output, your program can't. The second method could still be useful for testing or even for a command line application, but it should be named something like printQuarters instead.
public double getQuarters(){
return quarters;
}
Use this incorder to encapsulate quarters and hide it from being accessed by other programs. That means, you have to declare it as private quarters. Let see the second option:
public void getQuarters(){
System.out.println(quarters);
}
However, this seems wrong as getQuarters is not returning anything. Hence it would make more sense to refactor it as
public void printQuarters(){
System.out.println(quarters);
}
You answered your own question. For most definitions of the word "best", you should go with the first option.
Your question, however, does touch on the object-oriented programming topic of accessors and mutators. In your example, "getQuarters" is an accessor. It is usually best to use accessors to retrieve your values. This is one way to adhere to the Open/Closed Principle.
Also, the Java community has a coding convention for this and many tools and libraries depend on code following those conventions.
If all you need to do is display the value when this method is called, and you are ok with console output, then your System.out.println method will do the job. HOWEVER, a function that actually returns the variable is much more semantically correct and useful.
For example, while you may only need to print the variable for your current project, what if you came back later and decided that you were instead going to output your variable to a file? If you wrote your getQuarters function with a println statement, you would need to rewrite the whole thing. On the other hand, if you wrote the function as a return, you wouldn't need to change anything. All you'd have to do is add new code for the file output, and consume the function where needed.
A returning function is therefore much more versatile, although more so in larger code projects.
You return values to a specific point in your program, so that the program can use it to function.
You print values at a specific point in your program, so that you as an end user can see what value you got back for some function.
Depending on the function - for instance, yours - the result of quarters is no longer regarded in the program; all it did was print a value to the screen, and the application doesn't have a [clean|easy] way to get that back to use it.
If your program needs the value to function, then it must be a return. If you need to debug, then you can use System.out.println() where necessary.
However, more times than not, you will be using the return statement.
Option 1 is far superior.
It can be easily Unit Tested.
What if the spec changes and sometimes you want to print the result, other times put it into a database? Option 1 splits apart the logic of obtaining the value from what to do with it. Now, for a single method getQuarters no big deal, but eventually you may have getDimes, getEuros, etc...
What if there may be an error condition on quarters, like the value is illegal? In option 1, you could return a "special" value, like -1.0, or throw an Exception. The client then decides what to do.
I extracted someone's APK (Android app) to see the Java source code and saw a lot of return; code, even on void methods.
For example:
public void doSomething(){
do{
return; //This line makes the code below unreachable and can't compile in Eclipse
switch(num){
...
default:
return;
}
}while(...)
...
}
How come the app seems to run well on my phone?
I guess return; is like a shortcut to break from the method. Is that right?
If the method returns void then return; just exits out of the method at that statement, not running the following statements.
Yes, that is correct. Look at the bottom of http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html:
The return Statement
The last of the branching statements is the return statement. The
return statement exits from the current method, and control flow
returns to where the method was invoked. The return statement has two
forms: one that returns a value, and one that doesn't. To return a
value, simply put the value (or an expression that calculates the
value) after the return keyword.
return ++count; The data type of the returned value must match the
type of the method's declared return value. When a method is declared
void, use the form of return that doesn't return a value.
return;
To answer your first question: I assume this code is decompiled. Note that decompilers are not one to one converters of binary dex code to whatever Java code has been used to generate these binaries. They often have problems with parsing different control structures like loops and switches. Besides, the binary may be obfuscated, meaning that after compilation the binary is modified in a way to be fully operational, but harder to decompile and reverse engineer (basically to prevent what you're trying to do here :) ). They can add dead code, like return statement that shouldn't be there, mangle loops and if statements to confuse decompiled code, etc.
return keyword is used basically in a void method ,it helps to break the conditional statement to come out of method.
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();