Calculating AVL tree node balance from it's children nodes' balances - c++

Say I have an AVL tree such that it's nodes store their own balance factor as a single integer.
How can I calculate the balance factor of a node N if I know the balance factor of both it's left and right child.
Note that I DO NOT have the rHeight and lHeight, so bal(N) = lHeight - rHeight is not an option.

Short answer - you can't.
Long answer:
Consider these two trees:
A
/ \
B C A
/ \ / \ / \
D E F G B C
/ \ / \ / \ / \
H I J K L M N O
They have the same balance factor, but they aren't the same height.
So, if you only have the balance factor of the child, you don't know how high that subtree is, thus you can't use only that to calculate the balance factor of the parent.

Related

What is the O complexity of the number of "empty" nodes in an AVL tree?

We know that an AVL tree is usually very close to being balanced. Let's say we take an AVL tree and put it into an array (very similar to a heap, where the parent is index i, left child is 2i, and right child is 2i+1), how many empty indices would you get in terms of big O complexity?
So I know that the minimum number of nodes in a tree of height h = Fibonacci(h+2) - 1. So number of empty indices = 2^h - 1 - (Fibonacci(h+2) - 1) = 2^h - Fibonacci(h+2). But I don't know what to do next to prove it's complexity. I think it's O(log(n)), but I'm not sure.
If h is 0-based (as is the usual convention), the minimum number of nodes in an AVL tree with height h is F(h+3) - 1.
Let n = F(h+3) - 1 and let's try to solve for h to find the maximum height of an AVL tree with n nodes.
The closed form for F(x) is given by Binet's formula (see here for details):
F(x) = (phi^n - psi^n)/sqrt(5)
Therefore,
n = (phi^(h+3) - psi^(h+3))/sqrt(5) - 1
>= (phi^(h+3) - 1)/sqrt(5) - 1 since |psi| < 1
Solving for h yields
h <= log_phi(sqrt(5)(n + 1) + 1) - 3
<= 1.4405 log2(n)
A full tree with height h has 2^(h+1) - 1 nodes. Or in terms of n:
2^(h+1) - 1
<= 2^(1.4405 log2(n) + 1) - 1
= 2 * (2^log(n))^1.4405 - 1
= 2n^1.4405 - 1
Hence the number of empty nodes is bounded by
2n^1.4405 - 1 - n = O(n^1.4405)

Why does switching parent nodes not switch its children nodes?

For example, in this question: https://leetcode.com/problems/invert-binary-tree/
The correct solution is:
TreeNode* invertTree(TreeNode* root) {
if(root!=NULL)
{
TreeNode* tmp = (root->left);
root->left=root->right;
root->right=tmp;
invertTree(root->left);
invertTree(root->right);
}
return root;
}
However, why can we not just simply do:
TreeNode* invertTree(TreeNode* root) {
if(root!=NULL)
{
TreeNode* tmp = (root->left);
root->left=root->right;
root->right=tmp;
}
return root;
}
Wouldn't switching the parent nodes of the subtrees also switch its children?
Start with a tree (at least three levels):
A
/ \
B C
/ \ / \
D E F G
Swap the left and right children of the root:
A
/ \
C B
/ \ / \
F G D E
Notice that you are not yet at the inverted tree:
A
/ \
C B
/ \ / \
G F E D
Swapping the left and the right pointers only swaps the pointers, but the subtree pointers (further down) also have to be inverted. That's why you have to recurse down the left and right trees.

This program uses a ton of memory due to a huge vector, how can I prevent it from doing this?

I was browsing r/dailyprogrammer, and I came across a challenge I thought I could figure out.
I'm not going to go into detail, but the gist of it is that there are plants that produce 1 fruit every week, with the amount of fruit they produce increasing by 1 every week. These produced fruits are planted to create more plants. The program runs until enough fruits are being produced so that 1 person gets at least 1 fruit in a population, the size of which is determined by the user.
The point here is the vector I'm using to hold the plants is causing a huge amount of lag and makes the program take ages to run. Here is the entire thing, annotated for easier comprehension:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void funnyPlant() {
int startPlants, //initial plants (determined by user)
people, //population (determined by user)
fruits = 0, //fruits that the plants produce weekly
week; //integer representing time passed
cout << "Enter population: ";
cin >> people;
cout << "Enter initial plant quanity: ";
cin >> startPlants;
vector<int> plant(startPlants); //vector is created with each element representing
//1 plant, the value of which representing the amount
//of fruit it produces in a given week
cout << endl << "Processing, please wait..." << endl;
for (week = 0; fruits < people; ++week) {
fruits = 0; //fruits is reset because they are all planted immediately
for (int i = 0; i < plant.size(); ++i) {
fruits += plant[i]; //total fruits from each plant are tallied, to determine
//if there is enough for the given population
++plant[i]; //plant's fruit bearing capacity is increased by 1
}
for (int i = 0; i < fruits; ++i)
plant.push_back(1); //each fruit is planted, increasing the size of the vector
}
cout << week << " weeks required for sustainability" << endl;
cout << "( " << plant.size() << " plants producing " << fruits << " fruits)";
cout << endl << endl;
}
int main() {
funnyPlant(); //function is executed
system("pause");
return 0;
}
Now, the problem lies with my use of a vector to represent the amount of plants.
plant.push_back(1);
A higher population demands more time, which causes the amount of fruit being produced to reach astronomical quantities, which in turn causes the vector to expand to massive sizes, taking up a huge amount of memory.
Is there any way around this, or can I simply not use a vector? Any help would be greatly appreciated.
I do not like to demonstrations of full solutions but I feel like I have to as most suggestions are far from optimal.
[Please note: There is no math environment so it will look a bit ugly.]
You have the following informations:
At the beginning there are p_0 plants. Those plants will produce one fruit each (in the first week).
(There are no fruits at the beginning.)
Every week all plants are harvested and the f_w harvested fruits will be planted as new plants. These plant will produce one fruit each (in their first week).
All p_w already existing plants will increase fruit production by one fruit every weak.
There are P people who need to be fed, meaning you want to have at least P plants planted.
In short terms this reads
startvalues: p_0, f_0=p_0
recursive relation: w -> w+1
p_w+1 = p_w + f_w // the following week every harvested fruit of this week will be planted
f_w+1 = f_w + p_w+1 // the following week the production will increase according to the number of total plants after planting
= f_w + p_w + f_w // that is: every already existing plant will produce one more fruit and every new planted one will start producing one fruit
Given these relations one can easily implement an algorithm with just three variables (third es w which you probably want to know after reaching f_w >= P). This means: Only O(1) memory is needed! Runtime is O(weeks). As the fruit production is increasing extremely fast - more than exponential - which means that it is not linear in the number of people this seems to be a good result (and seems to be the best you can get).
Warning: Following is just a try. I did not find any better solution than the one above.
Let us go further and try to find a solution with a even better runtime.
Have a look at the recursive relation again. You may notice it is a simple linear dependency which you can express via a matrix vector multiplication v_n+1 = A * v_n:
/ p_w+1 \ / p_w + f_w \ / 1 1 \ / p_w \
\ f_w+1 / = \ p_w + 2*f_w / = \ 1 2 / \ f_w /
Now we can express the values of the total numbers of plants and fruit production in week w directly with only knowing p_0 and f_0(=p_0):
/ p_w \ / 1 1 \^w / p_0 \
\ f_w / = \ 1 2 / \ p_0 /
Remember: We want to know the minimal w where f_w >= P.
The problem is that this multiple matrix products are still O(weeks). But luckily the matrix is diagonalizable. (-> Wikipedia: Diagonalizable matrix, A = S*D*S^-1, if lazy use WolframAlpha to compute the diagonalization)
So the following equation holds:
/ 1 1 \ / (-1-sqrt(5))/2 (-1+sqrt(5))/2 \ / (3-sqrt(5))/2 0 \ / -1/sqrt(5) (5-sqrt(5))/10 \
\ 1 2 / = \ 1 1 / \ 0 (3+sqrt(5))/2 / \ 1/sqrt(5) (5+sqrt(5))/10 /
Now we can rewrite rewrite A^w to (S * D * S^-1)^w which is the same as S * D^w * S^-1.
So we get:
/ p_w \ / p_0 \
\ f_w / = S * D^w * S^-1 * \ p_0 /
As we only want to check for f_w we only need the equation
f_w = (cge^w + dif^w + che^w + djf^w) * p_0
where the constants c, g, ... are matrix entries of the matrices S, S^-1 and D:
/ a b \ / e 0 \ / g h \
S = \ c d / , D = \ 0 f / , S^-1 = \ i j /
[Note: f is not f_w and f^w is not f^w either. Sorry for the double usage of the letter f.]
Now reorder f_w and use c=d=1:
f_w = c(g+h)p_0 * e^w + d(i+j)p_0 * f^w
= (g+h)p_0 * e^w + (i+j)p_0 * f^w
As f_w shall be greater or equal to P (the number of people) we now search for the w that holds
P = (g+h)p_0 * e^w + (i+j)p_0 * f^w
<=> P/p_0 = (g+h) * e^w + (i+j) * f^w
Our new problem is that g+h != i+j. But we can use a trick. Rewrite the equation to
P/p_0 = (g+h) * e * e^(w-1) + (i+j) * f * f^(w-1)
with the relations
(g+h) * e = - 1 / sqrt(5)
(i+j) * f = 1 / sqrt(5)
we get
P/p_0 *sqrt(5) = - e^(w-1) + f^(w-1)
Well... This I did not get any further. Easy solutions to this equation or the following (equivalent with some minor constraints) are appreciated - or a prove that the recursive solution proposed above is already optimal.
a = x + x^c [need to be solved for x. a and c are some known constants derived from the above ones.]
Instead of holding everything in vector you should count number of plants with production of i, so suppose you have vector Cnt, on the first step you have Cnt[0] = startPlants, on next steps you "shift", which is copy Cnt[i] to Cnt[i + 1] in decreasing of i (which means that everything that produce i will produce i+1 on the next step). And for Cnt[1] you add sum of Cnt[i]*i before "shift".

How to rotate a treap or AVL-tree?

Sorry to bother you guys again, but I have a question and i haven't figured it out on my own for several days.
It is about the rotation of a treap, for example, to right rotate a treap at pos.
The question is how to link (or connect) pos->left to pos's original parent?
I found this code online, which works, but i didn't see how it solves my question, is it because of the use of *&? If so, could you help me explain it a little bit?
And what is the function of pos=b is this code?
void Treap::right_rotate(Node *&pos) {
Node *b = pos->left;
pos->left = b->right;
b->right = pos;
pos = b;
}
Thanks in advance!!
The tricky part is indeed the *& part. That declares it as a reference to a pointer (here's a link or two to some similar sample code, but I fear they may be more confusing than helpful).
By changing out the node to which the pointer points with pos = b, you can swap the contents to the different node without having to know the parent. The original reference is updated to be the new rotated node.
Here's a diagram just in case you needed a little overkill of what the rotation looks like (though it sounds like you understand that part).
Initial condition:
Node *&pos;
|
[P]
/ \
L R
/ \ / \
w x y z
You then store the left child since you are about to overwrite it as far as P is concerned.
Node *b = pos->left;
pos->left = b->right;
|
L [P]
/ \ / \
w x R
/ \
y z
Now we finish the rotation since since L is floating in space, breaking proper tree structure:
b->right = pos;
L
/ \ |
w [P]
/ \
x R
/ \
y z
We then finish the upkeep by updating the reference to the node pointer to be the new node that replaces the contents of that place in memory:
pos = b;
|
[L]
/ \
w P
/ \
x R
/ \
y z
Whomever was previously pointing to pos (pos's original parent) now points to the same spot in memory, but that value has now been replaced with the child that has been rotated.

finding height of a tree in sml

i want to find the height of a tree in sml.The tree is not a regular one it could have any number of nodes at a level.Futher the datatypes that it holds is also abstract.could someone help me out with it.
As other have said, then please post what ever definition of a tree you have, and what code you have come up with so far.
I assume that you have already defined your own tree structure or you have had it defined in the assignment, anyways this ought not to be your problem so here is simple binary tree structure using a Node and an empty Leaf as constructors.
datatype 'a tree = Leaf
| Node of ('a tree) * 'a * ('a tree)
val t1 = Node (Leaf, 1, Leaf)
val t2 = Node (t1, 2, Leaf)
val t3 = Node (Leaf, 3, Leaf)
val t = Node (t2, 4, t3)
Ascii representation of t
4
/ \
/ \
2 3
/ \ / \
1 * * *
/ \
* *
Where * represents the leafs
Given this representation of a binary tree, you could create a function that calculates the height in a bottom up maner. You mainly have to consider two cases:
What are the height of a tree only containing a leaf?
What are the height of a Node that has a left sub-tree of height l and a right sub-tree of height r?
If we look at t2 from the above example
2
/ \
1 *
/ \
* *
Then obviously the right sub-tree has height x (depends on how you define the height of leafs) and the left sub-tree has height 0. The Height of t2 must then be 1 (0+1).
Considering t then it has a left sub-tree of height 1 (as we have just found out) and the right sub-tree has height 0. Thus t must have height 2 (1+1)
I have seen many quick implementation of a height function that counts the root node, but this is not correct.
Here
height is defined as the number of links from the root to the deepest leaf