I have read many sources about AVL trees, but did not find anyone addressing this issue: When AVL tree gets unbalanced, which node should be rotated first?
Assuming I have the tree:
10
/ \
5 25
/
20
and I'm trying to add 15, both the root and its child 25 will be unbalanced.
10
/ \
5 25
/
20
/
15
I could do a RR rotation (or single rotation) of 25, resulting in the following tree:
10
/ \
5 20
/\
15 25
or a RL rotation (double rotation) about the root, creating the following tree:
20
/ \
10 25
/ \
5 15
I am confused about which rotation is the most suitable here and in similar cases.
The RR rotation is correct here. The rotation should be done as soon (as low) as the rule is broken. Which is for 25 here.
The higher rotations first don't necessarily break the rule and secondly would become too complex although it doesn't seem so here at the first sight.
Related
I am trying to rotate a tree to keep it balanced, but I am having hard time with this example. I am not so sure what I am doing wrong here.
I have below tree with L/R height difference 1 at node 30. So, I guess this tree is balanced.
30
/ \
20 60
/ \
10 25
I am adding 22 here and this is what I get after adding 22.
30
/ \
20 60
/ \
10 25
/
22
At node 20, L/R height difference is 1, but at node 30 it is 2. So, I guess it is not balanced any more. I am trying to right rotate the tree to balance it, but I am getting below tree.
20
/ \
10 30
/ \
25 60
/
22
After the rotation, node 20 has L/R height difference of 2 still.
Where am I doing wrong? Can this tree be balanced using rotation?
I can balance the tree using sorted array method like below, but I am really confused about rotation balance in this example.
22 25
/ \ / \
20 30 20 30
/ / \ / \ \
10 25 60 10 22 60
What am I doing wrong here?
Thanks a lot!!
There are basically four type of rotation in the AVL Tree.
Right-left
Left-Right
Left-Left
Right-Right
In your case, Left-Right should be applicable.
Here you need to perform two steps.
1:- Left rotate from 20 node. So your tree should like as below.
30
/ \
25 60
/
20
/ \
10 22
2:- Right rotate from 30 node. So your tree should be like as below.
25
/ \
20 30
/ \ \
10 22 60
You can refer the N website to understand the behavior. Here is one of the best link
This case requires a double rotation: rotate 25 up twice. I'm assuming that you're thinking about AVL trees, but all of the standard balanced binary trees need double rotations in some cases.
My best guess is that one rotation is always enough to balance an AVL tree when you insert or delete ONE element from an already balanced AVL tree.
Is one rotation always enough?
An example will help where more than one rotations are needed.
PS: I count RL/LR rotations as one rotation only.
For insertion I believe one is enough.
but for deletion:
consider this tree:
50
/ \
25 75
/ \ / \
15 40 60 80
/ / \ \
35 55 65 90
/
62
delete 15 , first the 25's balance factor is destructed, one rotation:
50
/ \
35 75
/ \ / \
25 40 60 80
/ \ \
55 65 90
/
62
but still, we have to check, now the tree's root's balance factor is destructed, have to be rotated again:
60
/ \
50 75
/ \ / \
35 55 65 80
/ \ / \
25 40 62 90
For insert 1 rotation is at most.
For delete the number of rotation is bounded by O(log(n)). Log(n) is the height of the tree.
More explanation on AVL deletion.
When you delete a node from AVL you might cause the tree unbalanced, which you have to trace back to the point where it is unbalanced. If the unbalanced point is the root. You have to rebalance the tree from top to bottom.
I wanted to draw a balanced binary search tree for numbers from 1 to 20.
_______10_______
/ \
___5___ 15
/ \ / \
3 8 13 18
/ \ / \ / \ / \
2 4 7 9 12 14 17 19
/ / / /
1 6 11 16
Is the above tree correct and balanced?
In answer to your original question as to whether or not you need to first calculate the height, no, you don't need to. You just have to understand that a balanced tree is one where the height difference between the tallest and shortest node is zero or one, and the simplest way to achieve this is to ensure that you always pick the midpoint of the possible list, when populating the top node in a sub-tree.
Your sample tree is balanced since all leaf nodes are either at the bottom or next-to-bottom level, hence the difference in heights between any two leaf nodes is at most one.
To create a balanced tree from the numbers 1 through 20 inclusive, you can just make the root entry 10 or 11 (the midpoint being 10.5 for those numbers), so that there's an equal quantity of numbers in either sub-tree.
Then just do that recursively for each sub-tree. On the lower side of 10, 5 is the midpoint:
10
/ \
5 11-thru-19 sub-tree
/ \
1-thru-4 6-thru-9
sub-tree sub-tree
Just expand on that and you'll end up with something like:
_______10_______
/ \
___5___ 15
/ \ / \
2 7 13 17
/ \ / \ / / \
1 3 6 8 11 16 18 <- depth of highest leaf node
\ \ \ \
4 9 12 19 <- depth of lowest leaf node
^
|
Difference is 1
The midpoint can be found at the number where the difference between quantities above and below that numbers is one or zero. For the whole list of numbers 1 through 20 inclusive, there are nine less than 10 and ten greater than 10 (or, if you chose 11 as the midpoint, the quantities are ten and nine).
The difference between your sample and mine is probably to do with the fact that I preferred to pick the midpoint by rounding down where there was a choice (meaning my right sub-trees tend to be "heavier"). Because your left sub-trees are heavier, you appear to have rounded up.
After choosing 10 as the initial midpoint, there's no leeway on the left sub-tree, you have to choose 5 since it has four above and below it. Any other midpoint would result in a difference of at least two between the two halves (for example, choosing 4 as the midpoint would have the two halves of size three and five). This can still give you a balanced sub-tree depending on the data but it's "safer" to choose the midpoint.
Given an AVL tree below:
23
/ \
19 35
/ \ / \
8 20 27 40
/
38
/
36
Is it ok to just do a single rotation at 40, to the right? Making it something like this:
23
/ \
19 35
/ \ / \
8 20 27 38
/ \
36 40
It still conforms tot he AVL property of having -+1 height compared to the left subtree.
In the answer it does a double rotation so the subtree at 35 above would look like this after:
23
/ \
19 38
/ \ / \
8 20 35 40
/ \
27 36
I don't understand when to do a double rotation and when to do a single rotation if they both do not violate the height property.
The double rotation may be due to a specific AVL algorithm in use. Both answers look like valid AVL trees to me.
If the original question was given with only the unbalanced AVL tree (and not the balanced tree before a node was added or removed), then the single rotation is a valid answer.
If the question provides the AVL tree before and after a node was added or removed, then the algorithm for rebalancing could result in the double rotation occurring.
Both answers are right, though according to the literature that I use:
The are four types of rotations LL, RR,LR and RL. These rotations are
characterized by the nearest ancestor A, of the inserted node N, whose
balance factor becomes 2.
The following characterization of rotation types is obtained:
LL: N is inserted in the left subtree of the left subtree of A
LR: N is inserted in the right subtree of the left subtree of A
RR: N is inserted in the right subtree of the right subtree of A
RL: N is inserted in the left subtree of the right subtree of A
According to these rules, the nearest ancestor whose balance factor becomes 2 is 40 in your example, and the insertion was made in the left subtree of the left subtree of 40 so you have to perform an LL rotation. Following these rules, the first of your answers will be the chosen operation.
Still, both answers are correct and depends of the algorithm you are using and the rules it follows.
If I am inserting items: 10,12,14,1,6 into a binary min heap one item after another how would the results look like, my problem is with the following
when i start i have:
10
then
10
/
12
then
10
/ \
12 14
then
1
/ \
10 14
/
12
but this is not right, so what is the right way to do that?
Note: this is a homework question, i am trying to understand the concept, if you don't feel comfortable solving the question (it is not the full question anyway) please provide an example with similar issue.
You have to add the new element as a child (or leaf exactly) to the heap (not as root), that means you put it in the first "right" free spot (or in your heap-array, just at the end).
Then you have to re-establish the heap conditions, this is called "heapify". This happens in two phases:
Repeatedly exchange the new element (general: the element that violates the heap conditions) with its parent node as long as it is smaller than the parent and it is not the root.
Repeatedly exchange the new element with the child with the smallest value, until the new element becomes a leave or both child nodes are bigger than the element itself.
That means
10
/ \
12 14
+ 1 leads to
10
/ \
12 14
/
1
And that violates the heap conditions, so you have to heapify
10
/ \
1 14
/
12
But this is still not right, so you have to heapify again
1
/ \
10 14
/
12
And there you are... everything OK now :-)
step1: 10
step2: 10
/
12
step3: 10
/ \
12 14
step4: 1
/ \
10 12
/
14
step5: 1
/ \
6 10
/ \
12 14