AVL Tree Balancing - java

I am working on an assignment that asks me to implement an AVL tree. I'm pretty sure I have the rotation methods correct, but I'm having trouble figuring out when to use them.
For example, the explanation in the book says that I should climb up the same path I went down to insert the node/element. However, I can't have any parent pointers.
Latest code:
public BinaryNode<T> insert(BinaryNode<T> node) {
if (this.getElement().compareTo(node.getElement()) > 0) {
if (this.getLeftChild() != null) {
BinaryNode<T> b = this.getLeftChild().insert(node);
if(!this.isBalanced()) {
this.balance();
}
return b;
} else {
this.setLeftChild(node);
}
} else if (this.getElement().compareTo(node.getElement()) < 0) {
if (this.getRightChild() != null) {
return this.getRightChild().insert(node);
} else {
this.setRightChild(node);
}
}
return this;
}
What I want to do here is climb back up the tree, but it can only check the balancing AFTER it inserts the node. Hence, this being in the else clause.
I also tried putting the balance code where R Samuel Klatchko suggested, but checked the balance on each insert. For example: If one inserts 7, 9, 5, 3, and 1 consecutively, I get a null pointer exception when trying to insert 1.
EDIT: One reason for the above may have something to do with the way I was doing the height. It works fine with a single right rotation if I calculate the height every time with height() but that breaks the O(log(n)) time of an AVL Tree.
Any thoughts on how to accomplish this?

You code is climbing up the same path you went down. Consider this code:
if (this.getLeftChild() != null) {
return this.getLeftChild().insert(node);
}
and modify it slightly:
if (this.getLeftChild() != null) {
boolean b = this.getLeftChild().insert(node);
// do something here
return b;
}
As the code returns from the recursive calls, each return brings you back to the parent. By not immediately returning the value of the recursive call, you have a chance to do your rebalancing.
Update for latest code
Don't forget to rebalance when you've inserted to the right.

You might try passing the parent pointer into the insert method, or you could convert insert into an iterative method and keep an explicit stack on which you record the path down the tree.
By the way, in order to choose which rotation to use, you can just know that a node is unbalanced, you have to know whether the deeper subtree is on the right or on the left. This means that your simple isBalanced method isn't quite enough. It's also inefficient, and will blow the AVL tree's O(log n) complexity, because you compute the heights each time.

Related

Recursion reverse a SingleLinkedList and print as a String

I was given the task to add a method reversed to a SingleLinkedList using recursion preferably.
public String reversed() {
StringBuilder b = new StringBuilder();
reversed(first, b);
return b.toString();
}
private void reversed(Node<E> n, StringBuilder b) {
if (n != null) {
reversed(n.next, b);
b.append(n.element);
b.append(ā€™\nā€™);
}
}
Seems to work very well when I test in eclipse.
However, I am not sure if I understand 100% why.
This is how I think. Let us imagine we have SingleLinkedList with 5 Nodes and we put in the first Node in the private method to reverse it.
Since n isnt null, its the first node. It will enter the if statement.
It will call on itself, but now with Node second, its not null since it will repeat....
Now it reaches Node 5, it calls itself, but then it will call on reversed (six,b) since Node six dosent exist and is null, it will not work. Therefore it moves to the row "b.append(n.element);" however. It now remembers where it started and appends "first.element"; after that it will append a new row.
What exaplins the logic that it will hereafter append second.element; Can someone explain how I should think to understand that it will now append the second element?
Thanks in advance, think I really need to understand this to under recursion fully in java
Each method call keeps its own state. Once you get to node 6, there will be 5 calls on the stack waiting for reversed(n.next, b) to finish. Each method can only continue after the call to reversed on the stack above it finishes.
In this example you have last in as the first to act, i.e. you have a non-tail recursive function (the recursive call is happening before you perform the action of that method).
Imagine if every time you got to reversed you replaced that method call with the code it would execute. Remember all the calls happens serially (there is only one thread, nothing can happen in parallel). You'd get something that looks like this:
if (n0 != null) {
Node<E> n1 = n0.next;
if (n1 != null) {
Node<E> n2 = n1.next;
if (n2 != null) {
Node<E> n3 = n2.next;
if (n3 != null) {
Node<E> n4 = n3.next;
if (n4 != null) {
Node<E> n5 = n4.next;
if (n5 != null) {
// would be null so nothing happens
}
b.append(n4.element);
b.append('\n');
}
b.append(n3.element);
b.append('\n');
}
b.append(n2.element);
b.append('\n');
}
b.append(n1.element);
b.append('\n');
}
b.append(n0.element);
b.append('\n');
}
You can see how this code gets pretty hard to read once the number of elements goes up. When we don't know exactly how long the list will be this approach breaks down... you wouldn't want to do this 10, 100, or possibly thousands of times!
This is exactly why recursion is so useful for applications like this. We are able to re-use the interesting logic without having to know the length of the list, and are able to reduce duplicated code significantly.
Just keep in mind that recursion comes at a memory cost. Each time you enter the recursive method you add state to the stack. Once you cap out the memory on your machine you'll have to begin looking at non recursive ways of performing this work.

Finding K-th to last element of a singly linked list

I am currently reading the book "Crack the Coding Interview" (5th edition). There is a particular problem in it saying Implement an algorithm to find kth to last element of a singly linked list. There are various approaches discussed to the problem. I am particularly confused by the recursive solution. It goes as follows (shamelessly copying it from the book):
public class IntWrapper {
public int value = 0;
}
LinkedListNode nthToLastR2(LinkedListNode head, int k, IntWrapper i){
if(head == null){
return null;
}
LinkedListNode node = nthToLastR2(head.next, k, i);
i.value = i.value + 1;
if(i.value == k) { // We've found the kth element
return head;
}
return node;
}
My question is: We are returning a LinkedListNode when we find that particular node and we are returning a LinkedListNode even when we don't find that particular node. So there is no means to tell kth node from any other node. Can anyone please tell me if my observation is correct or not? If yes, how can we make it correct (other than, of course doing a System.out.println before the return head because that would be just printing the node and not returning it) ?
The trick in this recursive function is that the recursive call happens first - this means that by the time any of the code after the call executes, we'll already be at the last node. Once we get to the end, our function will return null because there is nothing left (head is now null). The final function of our callstack returns null, which means that node = null. Now the function checks to see if the current node is the k-th one (using the accumulator i).
There are two possible cases:
We aren't at the correct node: Our function simply returns node, which as we recall is null. Thus for the next higher function in the callstack, things look just like if it had hit the end, except that i is larger.
We are at the correct node: We return head, not node (remember node = null). In this case, we propagate back up the callstack again, but this time instead of node being null at each layer, it's head, which is the node we want. Eventually we get back to the top, and return the correct element.
So, simply put, the function keeps returning null until we find the element, then it keeps returning the element.
Poorly drawn mspaint picture:
Short answer: Your observation is incorrect, the example works as is. To the expanation first simple recusion example:
Factorials: n! = n*(n-1)*(n-2)...*1
Recursive Function:
int fact(int n) {
if (n==1) {
return 1;
} else {
return n*fact(n-1);
}
}
So basically the function calls itself until it comes to the point where n==1 and then you get a result after the result has come through to the one you called. So basically
fact(3) = 3*fact(2) = 3*2*fact(1) = 3*2*1
The same happens in your example:
It starts by running through the list till the end by calling itself with the next element of the list
LinkedListNode node = nthToLastR2(head.next, k, i);
when it reaches the last node it starts returning stuff
if(head == null){
return null;
}
only then does the last one before that call go to the line
i.value = i.value + 1;
and starts counting from the last node.
Then checks if it has the kth node from the last by checking
if(i.value == k) {
and if it has it return the head it got.
If it hasn't it return the one it got returned from the one before. For example k=4 and seven node
head: 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> null
| returning
i= 7 6 5 4 3 2 1 v
3 <- 3 <- 3 <- 3 <-.-null<- null <- null
Each step is an independent evaluation of the same function knowing not who called it and waiting for the one it called to return something.
I'm not sure that the book you are using is that good. They access member variables without getters/setters. You would see that 15 years ago in Java, but it's a big no-no now. They are in their 5th edition (2011), but it seems they were lazy in did not update their examples as the Java conventions were evolving.
Their recursive solution is quite complicated. I wrote a alternate recursive solution below. It keeps a queue of the latest visited nodes. That queue is kept as small as possible. I am using Java 8's Optional where a returned empty value signifies that the list is too short.
Optional<LinkedListNode> recur(
LinkedListNode currentNode,
int nFromLast,
Queue<LinkedListNode> latestNodes) {
if (currentNode == null) { // went past the last node
if (latestNodes.size() > nFromLast)
return Optional.of(latestNodes.remove());
else // the queue is too short
return Optional.empty();
} else {
if (latestNodes.size() == (nFromLast + 1))
latestNodes.remove();
latestNodes.add(currentNode);
return recur(currentNode.getNext(), nFromLast, latestNodes);
}
}
It is called initially with an empty queue:
recur(list, k, new ArrayDeque())
[Warning: this paragraph below is at an advanced level.]
It might seem that my solution wastes memory by keeping the queue, but their solution keeps items in memory on the stack. My solution is tail recursive and theirs is not. Unfortunately, it is not an advantage for the time being since the JVM does not optimize for tail recursion. The JVM also keeps everything (including all copies of the queue) on the stack for my method. At least I think my solution is simpler.

Inserting an object into a quadtree in Java

I'm making a quadtree and need helping inserting an object into it. I understand the concept of doing it, but I'm not great with recursion and the way Java passes variables.
I have a Quadtree class which contains a Node called root. The Node class has four Nodes inside of it, which are the four quads that make it up. The root node is created when you create the quad tree, and the four nodes inside each node aren't created until I call createChildrenQuads(). However, for the root node, that method is called when you create the quad tree.
So my thought process on how to insert an item into a node is this:
Start at the root node
For each node:
Check and see which of the current node's children quad the current
item fits in
If it fits in one of them, insert it into that
node(call the recursive method and start over)
If it didn't fit into
any, add it to the current node's list of objects and be done
Based on that, I created this:
public void insert(Entity e) {
insert(root, e);
}
private void insert(Node n, Entity e){
Rectangle temp = e.getRectangle();
if (!n.childrenHaveBeenCreated())
n.createChildrenQuads(n.m_quadRect);
//first check which node it can go into
if ( n.NW.m_quadRect.contains(temp)) {
n.NW = insert(n.NW, e);
return;
}
if ( n.NE.m_quadRect.contains(temp)) {
n.NE = insert(n.NE, e);
return;
}
if ( n.SW.m_quadRect.contains(temp)) {
n.SW = insert(n.SW, e);
return;
}
if ( n.SE.m_quadRect.contains(temp)) {
n.SE = insert(n.SE, e);
return;
}
n.m_objects.add(e);
}
I think quadtree-wise, the logic I have there is fine. When I debug the code, it looks like everything works as it should. However, I believe my problem is that Java passes parameters by value and not reference, so while I add it at the correct spot, it doesn't get "saved" because it is just a local variable. I believe that is the problem, but I could be wrong.
So I tried changing it a bit to make it so that the insert method returns the current node, so that everything should get "saved" correctly. This is what I came up with:
public void insert(Entity e) {
root = insert(root, e);
}
private Node insert(Node n, Entity e) {
Rectangle temp = s.getRectangle();
if (!n.childrenHaveBeenCreated())
n.createChildrenQuads(n.m_quadRect);
//first check which node it can go into
if ( n.NW.m_quadRect.contains(temp)) {
n.NW = insert(n.NW, e);
return n;
}
if ( n.NE.m_quadRect.contains(temp)) {
n.NE = insert(n.NE, e);
return n;
}
if ( n.SW.m_quadRect.contains(temp)) {
n.SW = insert(n.SW, e);
return n;
}
if ( n.SE.m_quadRect.contains(temp)) {
n.SE = insert(n.SE, e);
return n;
}
n.m_objects.add(e);
return n;
}
However, I still have the same problem. Now I'm not sure what my problem is.
I'm using this for a game, and I have it so that it draws an outline around where all of the quads are, and I can click to add an Entity into the quadtree. Both versions of my code seem to act the same. What happens is when I add an entity to the quadtree, it gets added and stays there, so I guess my theory of it not getting "saved" because of how Java passes references is wrong.
However, my code should(at least in my mind should) place each entity into the quadtree to as low of a level as it can, creating new children quads in each node as it goes down the tree. What actually happens though, is that sometimes it seems to just add the new entity into the current quad, not going down the tree at all, or it goes down a level or two and that is it, when it can easily go down a few more levels.
Can anyone see anything wrong with the code or my logic at all?
I think it is the way you've structured your program. The quadtree gets to test every quadrant, but it also alway adds the element at the end... So even though it will recursively make it's way to the bottom, on the way back up it will always run your last n.m_objects.add(e);
therefore changing where it is added on the way back up through the recursion. You need to change it to more of an If (..) else if (...) else (...)

Trying to implement level order traversal on a binary search tree in Java

Okay, so I'm trying to make a method that will return the level order of a basic binary search tree that carries int values in its nodes. I've figured out most of the other methods, such as insertion, post order and pre order, but I keep running into the same problem with the level order method
Here's the code:
private DoubleStackQueue<Node> queue = new DoubleStackQueue<Node>();
//this is a queue that uses two stacks, one for the front and one for the back.
//it works just like a queue.
public String levelOrder(){
s = ""; //The s is a private String that is implemented earlier
queue.add(this);
while (!queue.isEmpty())
{
Node node = (Node)queue.remove();
if (!(node.equals(null))) {s += ""+node.getVal();}
if (!(left.equals(null))) {queue.add(node.left);}
if (!(right.equals(null))) {queue.add(node.right);}
}
return s;
}
The main problem that I am having is that, when the program gets to a leaf node, it still adds its children to the queue, even though there are no children, just null, so I'll get a queue that has two nulls in front of the actual item in it. I originally had the if statements as (left != null) and such, but that didn't work either. I'm just trying to figure out how to make the program recognize when there aren't any children. What do I need to do?
Several comments:
The primary issue is that you're using left and right instead of node.left and node.right in your comparisons.
To compare against null use if (var != null). Do not use equals(). If a variable is null you cannot call methods on it as that will trigger NullPointerExceptions.
Once you have fixed your code you will never have null inserted into the queue. The first object you add is this which is guaranteed to be non-null, and subsequently you always check for null before inserting items onto the queue. That means your first if (node != null) check is unnecessary.
The cast in (Node) queue.remove() should be unnecessary. Your compiler ought to warn you about this.
Result:
queue.add(this);
while (!queue.isEmpty())
{
Node node = queue.remove();
s += "" + node.getVal();
if (node.left != null) { queue.add(node.left); }
if (node.right != null) { queue.add(node.right); }
}
Within your code I can find the lines
if (!(left.equals(null))) {queue.add(node.left);}
if (!(right.equals(null))) {queue.add(node.right);}
where in the condition it states left and right which are nowhere defined in the parts you show but on the right it reads node.left and node.right. Is this intentionally? I'd expect also node.left and node.right in the if conditions.
Look at this question: Level-order tree traversal
I believe this is the same thing you're trying to achieve, is it not? This is a pretty classic problem, so in my experience it's been discussed over-and-over before.

Calculate the depth of a binary search tree?

I am having difficulty calculating the summation of depths [the sum of the individual depths for all children of the root] for a given BST. I have the total number of nodes for the tree, and I am trying to calculate the average depth for the tree, requiring I have this depth sum.
Recursion and I don't get along very well.. I am finding this problem very difficult. I would like to see a recursive solution though, if possible.
NOTE:
I have created accessors Node.getLeft() and Node.getRight()
You just need to keep a depth counter as you traverse the tree (look up tree traversals if you have to) and add the value of the counter every time you reach a node. Then just divide by the number of nodes.
This looks like homework so I'm not providing a more detailed solution.
Think about how you would go about this canonically by hand if I had presented a picture of a BST to you on a sheet of paper. When you're at a node, what information do you need to keep track of? How does one find the height of a given node?
From here, try to translate this into pseudocode or even straight into Java. If you're having trouble, feel free to comment so users can help you out.
Is this homework? If so tag the question as such.
You could create a method that:
has a node reference and a depth as arguments
increment depth
if node is not a child node call recursively for left and right and update sum accordingly
otherwise return sum + depth
Once you have this devide by the number of children in the tree to get the average depth.
We need to visit all leaf nodes and figure out how deep they are. This suggests:
Give your node-visiting function an extra argument. It needs to know not just where it's going but also how deep it is. Every time it's called, it's called on to go deeper, so your node visitor just has to increment the depth number it got from the caller.
Now one of 2 things can happen:
Either the node you found is a leaf node, i.e. it doesn't have any children; in this case, your visitor needs to return its depth to the caller. Yeah, it just returns the number it got from the caller, + 1.
or it's not a leaf node. In that case, it will have either 1 or 2 children. We need to get those depth reports from our kids back up to the caller, so just return the sum of the depths returned by the children.
By the magic of recursion, the number returned to the root's visitor will be the sum of the depths of all children.
To get an average depth, you'll want to divide this by the number of leaf nodes; which I'd leave to a second traversal to calculate. It could be done in one, but it would be a little more complicated.
Since this is homework, I don't want to just give you an answer. Instead, here's a recursive way to calculate the length of a singly linked list. Hopefully this will demonstrate recursion in a way you can understand, and you can extrapolate from there to solve your BST problem.
public final class LL {
public final int value;
public LL next;
public LL(final int value) {
this.value = value;
}
public void add(final int value) {
if (null == next) {
next = new LL(value);
} else {
next.add(value);
}
}
/**
* Calculate the length of the linked list with this node as its head (includes this node in the count).
*
* #return the length.
*/
public int length() {
if (null == next) {
return 1;
}
return 1 + next.length();
}
public static void main(final String... args) {
final LL head = new LL(1);
head.add(2);
head.add(3);
System.out.println(head.length());
System.out.println(head.next.length());
}
}

Categories