Reputation: 123
I am working on an AVL tree such that each Node holds the deepest sub-tree beneath it. Here is an example of the tree, where the representation is value: height.
0: 2
\
1: 1
\
2: 0
To check the balance, I used the following function given an AVL Tree node or undefined. Following code snippet is written in TypeScript. The formula used is left - right
depth, with undefined child nodes returning -1.
private balanceFactor(currentNode: AVLTreeNode<E> | undefined): number {
if (currentNode === undefined) {
return -1;
}
let leftHeight = currentNode.hasLeft() ? currentNode.getLeft().getHeight() : -1;
let rightHeight = currentNode.getRight() ? currentNode.getRight().getHeight() : -1;
return leftHeight - rightHeight
}
To implement the logic code of the rotations, I found a previous stack post: https://stackoverflow.com/a/19281663/10448256
The post deals the following logic for the double rotations:
balance(N) = Depth(Nleft) - Depth(Nright)
if (balance(P) > 1) {
if (balance(L) < 0) {
rotate_left(L);
}
rotate_right(P);
}
else if (balance(P) < -1) {
if (balance(R) > 0) {
rotate_right(R);
}
rotate_left(P);
}
Consider the following double rotation scenario:
2: 2
/
1: 1
\
0: 0
When the balance factor is called on node 2, it creates a BF of two (2 - 0), and since the right is undefined, the balance factor of the right is -1. This results in a double rotation, correctly creating the following tree:
1: 1
/ \
0: 0 2: 0
While the double rotation works, it does not allow for single rotations. If the first example is tried again:
2: 2
\
1: 1
\
0: 0
It creates a balance factor of 2 at value 2, where the left node is a -1 because it is undefined, incorrectly resulting in a double rotation detection.
What logic should I use to identify the difference between double and single rotations?
Upvotes: 0
Views: 316
Reputation: 350270
The logic that is implemented in the code you found in a related question is correct.
While the double rotation works, it does not allow for single rotations.
The inner if
condition in the referenced code determines whether a double or single rotation should occur.
If the first example is tried again:
2: 2 \ 1: 1 \ 0: 0
It creates a balance factor of 2 at value 2, where the left node is a -1 because it is undefined, incorrectly resulting in a double rotation detection.
This is due to an error in your balanceFactor
function. When a node is absent, you have there an empty tree. Such a tree is balanced. There is no good reason to return -1 in that case as if that empty tree is out of balance. You should return 0:
private balanceFactor(currentNode: AVLTreeNode<E> | undefined): number {
if (currentNode === undefined) {
return 0; // Correction
}
let leftHeight = currentNode.hasLeft() ? currentNode.getLeft().getHeight() : -1;
let rightHeight = currentNode.getRight() ? currentNode.getRight().getHeight() : -1;
return leftHeight - rightHeight
}
Remark: it is not efficient to call getHeight
in the process of determining the balance factor. This can be done incrementally without the need to know a node's height. See for instance this implementation which uses a lookup table (matrix) for the balance factors found in the two nodes that participate in a rotation, giving the new balance factors for those nodes.
Upvotes: 0