I have this homework problem and I have completed all methods except this one, isPerfectlyBalanced().
All my tests pass except one that should return false but instead returns true. I have attached my current code and the test that is failing. Any description on how to go about this or even let me know where my code is wrong is appreciated!
private boolean isPerfectlyBalanced(Node node) {
if (node == null) {
return true;
}
if(size(node.left) == size(node.right)) {
return true;
}
isPerfectlyBalanced(node.left);
isPerfectlyBalanced(node.right);
return false;
}
public boolean isPerfectlyBalancedS() {
// TODO
if (root == null) {
return true;
}
return isPerfectlyBalanced(root);
}
Here is my test that is failing:
assertFalse(set.isPerfectlyBalancedS());
Thank you!
My size method:
private int size(Node node){
if (node == null){
return 0;
} else {
return (size(node.left) + 1 + size(node.right));
}
}
public int size() {
// TODO
return size(root);
}
On the last line of the first method, you probably want to do this:
return (isPerfectlyBalanced(node.left) && isPerfectlyBalanced(node.right));
instead of
isPerfectlyBalanced(node.left);
isPerfectlyBalanced(node.right);
return false;
In your code, you dismiss the result of the isPerfectlyBalanced on the subtrees and always return false.
Related
I have written a method that searches a tree to test if any integers are negative.
But I am struggling to get the right Boolean value returned. Any pointers as to where I am going wrong?
What I want to achieve is that as soon as the condition statement is met a false is returned but unfortunately my code is always returning a true
static boolean allE(Tree<Integer> x) {
if (x.isEmpty()) return true;
else {
if (x.getValue()%2 != 0) return false;
}
allE(x.getLeft());
allE(x.getRight());
return true;
}
When you recurse on allE you need to consider the result of that recursion. Easiest fix I see, change
allE(x.getLeft());
allE(x.getRight());
return true;
to
return allE(x.getLeft()) && allE(x.getRight());
Although, I think it makes more sense to write the algorithm such that you recurse on even explicitly. And allE saves three letters compared to allEven (please use meaningful names for methods and variables). Something like,
static boolean allEven(Tree<Integer> node) {
if (node.isEmpty()) {
return true;
} else if (node.getValue() % 2 == 0) {
return allEven(node.getLeft()) && allEven(node.getRight());
}
return false;
}
You're not using the results of your recursive tests properly.
It should be:
if (x.isEmpty()) {
return true;
}
boolean thisNodeEven = x.getValue() % 2 == 0;
return thisNodeEven && allE(x.getLeft()) && allE(x.getRight());
I suppose you need to evaluate the return-value of the recursive calls:
static boolean allE(Tree<Integer> x)
{
if (x.isEmpty())
return true;
else {
if (x.getValue()%2 != 0) return false;
}
if(!allE(x.getLeft()) || !allE(x.getRight()))
return false;
return true;
}
So I have written an implementation of a BST in Java. My goal is to make it balanced aswell, more precisly an AVL tree. I am having some problem though, I don't know how to implement the trinodeRestructering method(ie the method that balances the tree) I have tried various things but these pointers are sometimes difficult to deal with and I am not sure how to do this recursivly. Down below is my code for adding a new element and the method to check if we are more than 2 steps difference in the tree.
add and balancing method:
private TreeNode insert(TreeNode currN, TreeNode newN) {
if (currN == null) {
return newN;
}
if (currN.getData() == newN.getData()) {
throw new IllegalArgumentException("Value already exists.");
}
if (newN.getData() < currN.getData()) {
if (currN.getLeft() == null) {
currN.setLeft(newN);
} else {
insert(currN.getLeft(), newN);
}
} else {
if (currN.getRight() == null) {
currN.setRight(newN);
} else {
insert(currN.getRight(), newN);
}
}
if (needBalancing()) {
trinodeRestructering(currN);
}
return currN;
}
private TreeNode trinodeRestructering(TreeNode currN) {
//Not sure what to do here.
return currN;
}
height checking method.
public boolean needBalancing(){
if(height(root) == -1){ // true if we need to balance
return true;
}else{
return false;
}
}
private int height(TreeNode node){
if (node == null)
return 0;
int left = height(node.getLeft());
int right = height(node.getRight());
if (left == -1 || right == -1)
return -1;
if (Math.abs(left - right) > 1) {
return -1;
}
return Math.max(left, right) + 1;
}
I might add that I got an working inOrder method, perhaps I could use it to balance my tree?
I have below code but when i try to run the check function its giving me stackOverFlow error please help
when i debugged it its going till "return true;", but also entering else.
NOTE :
I have this data in my collection :
{1=[2, 3], 2=[3], 3=[4], 4=[3], 5=[6], 6=[5]}
How can i find the link between two nodes
private Map<Integer, ArrayList<Integer>> graphList = new HashMap<Integer, ArrayList<Integer>>();
private boolean checkLink(ArrayList<Integer> dataListFirst, int match) {
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (data == match) {
return true;
} else {
checkLink(graphList.get(data), match);
}
}
}
return false;
}
You are not using the retun value of your recursive call:
if (data == match) {
return true;
} else {
checkLink(graphList.get(data), match); // <--- Return value unused
}
You can modify your code to check if the recursive calls find your element:
private boolean checkLink(ArrayList<Integer> dataListFirst, int match) {
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (data == match || checkLink(graphList.get(data), match)) {
return true;
}
}
}
return false;
}
This code still could has a problem if your graph has cycles, you could return false in your function when you are trying to check the same value again.
// Just call the recursive function with an empty list of elements
private boolean checkLink(ArrayList<Integer> dataListFirst, int match) {
return checkLink(dataListFirst, match, new ArrayList<Integer>());
}
private boolean checkLink(ArrayList<Integer> dataListFirst, int match, List<Integer> nodes) {
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (nodes.contains(data)) {
return false;
}
nodes.add(data);
if (data == match || checkLink(graphList.get(data), match, nodes)) {
return true;
}
}
}
return false;
}
It seems to me you only want to make a recursive call after checking all the elements of the current ArrayList. And you should use the value returned by the recursive call (that's the reason your recursion didn't end after return true;) :
private boolean checkLink(ArrayList<Integer> dataListFirst, int match)
{
if (dataListFirst != null) {
for (int data : dataListFirst) {
if (data == match) {
return true;
}
}
for (int data : dataListFirst) {
boolean found = checkLink(graphList.get(data), match);
if (found)
return found;
}
}
return false;
}
I'm not sure this will work in all cases, though, since if there are cycles in the graph you may get into an infinite recursion without ever finding the desired node.
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);