Extract the root from a max heap - heap

I am struggling to write a recursive algorithm to extract the max(root) from a max heap.
The heap is constructed as a tree.
I know that I should swap the last node with the root and push it down recursively. But there is no pseudocode on the internet or stack overflow to deal with trees.
The extract algorithms that I have seen are based on arrays.
So let's say that I find the right most leaf.
Is there any solution that you can suggest?
void find_last(heap_node* root,int level,int* last_level,bool isRight,heap_node** res){
if(root == NULL)
return;
if(isRight && !root->left && !root->right && level > *last_level){
*res = root;
*last_level = level;
return;
}
find_last(root->right,level+1,last_level,true,res);
find_last(root->left,level+1,last_level,false,res);
}
And i made a function call like this
heap_node* last = NULL;
int last_level = -1;
find_last(root,0,&last_level,false,&last);
That is the code of finding the deepest right node.
And it is not working :D

Efficiently finding the last node in a heap that's implemented as a tree requires that you maintain a count of nodes. That is, you know how many items are in the heap.
If you know how many items are in the heap, then you get the binary representation of the number and use that to trace through the tree to the last node. Let me give you an example. You have this heap:
1
/ \
2 3
/ \ / \
4 5 6
There are 6 items in the heap. The binary representation is 110.
Now, moving from right to left in the binary representation. You remove the first '1' and you're at the root node. The rule is that you go right if the digit is '1', and left if the digit is '0'. At the root node, you have 10. So you go right and remove that digit, leaving you with 0. You're at the node marked "3". The remaining digit is 0, so you go left. That puts you at the last node in the heap.
The algorithm for sifting down through the heap is the same regardless of whether the heap is represented as an array or as a tree. The actual steps you take to swap nodes is different, of course. When swapping nodes, you have to be careful to set the child pointers correctly. One place people often forget is when swapping the root node with the last node.
My suggestion is that you code this up and then single-step in the debugger to make sure that you have the pointer assignments right.

Related

BST isBST() explanation

So I found this isBST() function on this site:
static struct node *prev = NULL;
bool isBST(struct node* root)
{
// traverse the tree in inorder fashion and keep track of prev node
if (root)
{
if (!isBST(root->left))
return false;
// Allows only distinct valued nodes
if (prev != NULL && root->data <= prev->data)
return false;
prev = root;
return isBST(root->right);
}
return true;
}
I am having a little bit of trouble following whats going on. Mainly
if (!isBST(root->left))
return false;
and
if (prev != NULL && root->data <= prev->data)
return false;
The if (prev != NULL && root->data <= prev->data) seems backwards to me for some reason. I would think it should be if (prev != NULL && root->data >= prev->data) because if the root->data was larger then it would be false. I understand that we are doing an in order walk of the tree and checking if it is in order. However, it is what each line is actually doing that is confusing me.
Could somebody please elaborate on what is going on with this function. Thanks
First of all, any time if we see a contradiction we can immediately return false - think of it as a short-circuiting. The rest of the tree is irrelevant at that point.
The two isBST calls are simple part of the recursion for the in-order walk.
As we go in-order, the values are strictly increasing (no duplicates). So if we see a mismatch, we can return false, so this is the right condition:
root->data <= prev->data
I couldn't format an example in the comments so I left here one showing where #JerryCoffin's solution will fail:
3
/ \
2 5
/ \
1 4
Okay, the basic idea here is that it starts by descending the tree all the way to the left-most node. That's because the first thing it does as it's called is check that root isn't a null pointer, and if it's not null, calls itself recursively on the left sub-tree. When it gets to the left-most node, the isBST(root->left) passes in a null pointer, so it returns true. So far, so good.
Then it checks whether prev is a null pointer (which, in this first descent into the left-most leaf, it will be). Then it stores the current root into prev, and checks the right sub-tree.
In the right sub-tree, it does the same--descends to the far-left node, returns true once, and gets back to the last "real" node (i.e. something other than a null pointer). This is where it gets interesting. It gets to the if statement, but this time, prev != NULL, so it checks that the value in the current node is greater than the value in the node referred to by prev.
For example, let's consider a tree like this:
10
/ \
4 12
/ \ / \
3 5 11 14
The first place things get interesting is when it's returned up to the 4 node. At this point it sets prev to point to the 4 node, then checks the right descendant from there, the 5 node. To be a valid tree, these two have to be in order, so if root (current the 5 node) is <= prev (currently the 4 node) the tree would be invalid, so it would return false.
When it finishes that, it sets prev to point to the 5 node, and checks its right sub-tree (which immediately returns true, because it doesn't have a right descendant).
Since that doesn't change prev, it's still pointing at the 5 node. So now we return to actual root of the tree, with prev pointing at the 5 node, and root pointing at the 10 node. Again, if root were pointing at a value <= to prev, we'd have an invalid tree, so if that happened, we'd return false.
I won't go through all the rest--by this point, I think the pattern is fairly apparent. In particular, every time it looks at the value at prev, it's pointing to a node that's to the left of the "current" root, so it requires that the current root be greater than the value at prev.
I believe this can be cleaned up (quite a bit) though. I really dislike using a static here, among other things. At the very least, this should be passed as an extra parameter instead of using a static variable.

Calculating depth of a node of a tree with certain constraints in C++

I have a tree in which there are 3 levels. There is a root node, the root node has 3 leaf nodes and all 3 leaf nodes have 3 other leaf nodes. The nodes represent servers. Now, I have to calculate the depth of a node at for a given level. The depth is calculated as follows:
1) If a server(node) is "up" at any level and any column, then the depth of that node is 0.
2) If a server is in the last level and is "down", then depth of that node is infinity.
3) For all other cases, the depth of the node is the max depth of it's leaf nodes + 1. By max depth, it means the majority value that has occurred in it's child nodes.
A bottom up approach is followed here and hence, the depth of the root node is the depth at level 1. The level is taken as the input parameter in the program. Now, I have to calculate the depth of the root node.
I have made some assumptions regarding the program:
1) To find child nodes, follow the child pointer of the parent node.
2) To find all nodes in a given level, traverse the child nodes from root till I reach that level and make a list of them.
3) Assign the values according to the given constraints.
I am not sure whether my approach is right or not. Please help me guys. Thank you.
I think you want something along the lines of the following pseudocode:
int nodeStatus(const Node& n) {
int status = 0;
if (n.isUp)
return 1;
else if (n.isLeaf)
return -1;
else {
for (Node child : n.children)
status += nodeStatus(child);
}
if (status > 0)
return 1;
else
return -1;
}
This is a recursive method. It first checks if the node is up, in which case it returns 1. Then if the node is down and is a leaf it returns -1 as this is a failure with no children. Finally, if n is an intermediate node then it recursively calls this method again for all the children, summing the result. The final if statement then tests whether the majority of the children are classed as 1 or -1 and returns the value accordingly. Notice that by using the values 1 and -1 it's possible to just sum the children up and providing each node definitely has 3 (or an odd number of) nodes then there will never be a situation where status == 0 which would be the case where there is no majority case.
You will need to define a struct called Node somewhere that looks like this:
struct Node {
Node(bool isUp, bool isLeaf);
bool isUp;
bool isLeaf;
std::Vector<Node> children = new std::Vector<Node>(3);
}
I hope this answers your question, but it may be that I've interpreted it wrong.

Last man standing , used circular linked list

Question : A company hiring candidates, makes them sit in a circle.
They select every second candidate and he leaves the circle (thus circle keeps getting smaller), till only 1 is left.
So, if there are 5 people, it'll be like :-
1 2 3 4 5
1 3 4 5 (2 is selected)
1 3 5 (4 is selected)
3 5 (1 is selected)
3 (3 is left, does'nt get the job!)
Jhon an oversmart guy doesn't want to be a part of this spiteful company.
Where does he stand if he knows that there are 560 people in total.
Ans : I tried to make a program where you enter n(number of candidates)
and it'll print the value of the one seat that will go unselected.
I Used circular linked list and deletion.
Please bear with me , as i am fairly new to coding .
My program works for inputs 2, 4, 8, 16, 32, 64 and so on as ans in all these is 1.
But any other input and it's not working.
#include <iostream>
using namespace std;
struct node
{
node* ptr;
int data;
}start;
int main()
{
node *start=NULL;
int n;
cout<<"Enter the number of students : ";
cin>>n;
node *temp=new node;
temp->data=1;
temp->ptr=NULL;
start=temp;
for(int x=2;x<=n;x++)
{
node* temp1=new node;
temp1->data=x;
temp->ptr=temp1;
temp1->ptr=start;
temp=temp1;
}
node* temp2=start;
do
{
cout<<temp2->data<<" ";
temp2=temp2->ptr;
}while(temp2!=start);
cout<<endl;
//delete bigins here
temp2=start;
node* temp3=temp2->ptr;
do
{
temp2->ptr=temp3->ptr;
temp3->ptr=NULL;
delete temp3;
temp2=temp2->ptr;
temp3=temp2->ptr;
}while(temp2->ptr!=start);
temp2=start;
do
{
cout<<temp2->data<<" ";
temp2=temp2->ptr;
}while(temp2!=temp3);
cout<<endl;
}
My program works for inputs 2, 4, 8, 16, 32, 64 and so on as ans in all these is 1.
This is a good observation. Actually the answer is just a small step from here.
You have n candidates, and you select 1 each time. If n is x + 2^k (with the biggest possible k), after x steps you have 2^k candidates left and the next candidate in the line is the answer. So the answer is 2x+1.
1 2 3 4 5 6 7
^ ^ ^ |
removed |
answer
Note: This exercise can be found in Concrete Mathematics: Foundation for Computer Science. I highly recommend it.
The issue lies in the core loop:
do {
temp2->ptr=temp3->ptr;
temp3->ptr=NULL;
delete temp3;
temp2=temp2->ptr;
temp3=temp2->ptr;
} while (temp2->ptr!=start);
This loop goes through the data once only: it stops when it gets to the end of the first set of removals, because it stops the first time it gets back to start. That's why you always get the answer 1, which, as you point out, is correct when the list length is a power of 2.
Rather, it should loop until there is only one node left, which will point to itself as the next node. So the last line of the do ... while loop should be:
} while (temp2->ptr != temp2)
Clearly the world has moved on: the first time I heard this puzzle it was about pirates drinking poison to determine who got the treasure!
to greatly simplify your solution, implement a "soft delete". Put a flag on your node struct called "int deleted" and initialize it to 0. Each time you want to delete a node, just set deleted = 1. Your pointer logic in your question is having problems and this gets rid of most of it.
When you're looking for the next one to delete, if the node has deleted == 1, then don't count it as one of the remaining ones, just keep going until you find the second node with deleted = 0, and set it to 1.
You don't even really need a circular list, or even a list at this point. You can just use an array of ints with values of 0 or 1. If you keep a count of how many are still around, then you can stop as soon as you get to just one remaining, otherwise you would have to traverse the whole array to make sure there are none left.
This isn't as fast, as your list never gets smaller and you're looking at a lot of deleted entries, but it's a ton simpler.
There is a small error in the second do while loop (deletion). The while statement forces the termination of loop after iterating through it once, i.e., once it reaches back the the start node, it exits. You need to change the line
while(temp2->ptr!=start);
to
while(temp2->ptr!=temp2);
Also the last do while loop seems to run into an infinite loop because of the statement just above it:
temp2 = start;
During deletion, you do not keep track of the start pointer which gets removed as soon as element 1 is deleted. Thus temp2 points to garbage then. Removing this line should fix that too.

Finding Depth of Binary Tree

I am having trouble understanding this maxDepth code. Any help would be appreciated. Here is the snippet example I followed.
int maxDepth(Node *&temp)
{
if(temp == NULL)
return 0;
else
{
int lchild = maxDepth(temp->left);
int rchild = maxDepth(temp->right);
if(lchild <= rchild)
return rchild+1;
else
return lchild+1;
}
}
Basically, what I understand is that the function recursively calls itself (for each left and right cases) until it reaches the last node. once it does, it returns 0 then it does 0+1. then the previous node is 1+1. then the next one is 2+1. if there is a bst with 3 left childs, int lchild will return 3. and the extra + 1 is the root. So my question is, where do all these +1 come from. it returns 0 at the last node but why does it return 0+1 etc. when it goes up the left/right child nodes? I don't understand why. I know it does it, but why?
Consider this part (of a bigger tree):
A
\
B
Now we want to calculate the depth of this treepart, so we pass pointer to A as its param.
Obviously pointer to A is not NULL, so the code has to:
call maxDepth for each of A's children (left and right branches). A->right is B, but A->left is obviously NULL (as A has no left branch)
compare these, choose the greatest value
return this chosen value + 1 (as A itself takes a level, doesn't it?)
Now we're going to look at how maxDepth(NULL) and maxDepth(B) are calculated.
The former is quite easy: the first check will make maxDepth return 0. If the other child were NULL too, both depths would be equal (0), and we have to return 0 + 1 for A itself.
But B is not empty; it has no branches, though, so (as we noticed) its depth is 1 (greatest of 0 for NULLs at both parts + 1 for B itself).
Now let's get back to A. maxDepth of its left branch (NULL) is 0, maxDepth of its right branch is 1. Maximum of these is 1, and we have to add 1 for A itself - so it's 2.
The point is the same steps are to be done when A is just a part of the bigger tree; the result of this calculation (2) will be used in the higher levels of maxDepth calls.
Depth is being calculated using the previous node + 1
All the ones come from this part of the code:
if(lchild <= rchild)
return rchild + 1;
else
return lchild + 1;
You add yourself +1 to the results obtained in the leaves of the tree. These ones keep adding up until you exit all the recursive calls of the function and get to the root node.
Remember in binary trees a node has at most 2 children (left and right)
It is a recursive algorithm, so it calls itself over and over.
If the temp (the node being looked at) is null, it returns 0, as this node is nothing and should not count. that is the base case.
If the node being looked at is not null, it may have children. so it gets the max depth of the left sub tree (and adds 1, for the level of the current node) and the right subtree (and adds 1 for the level of the current node). it then compares the two and returns the greater of the two.
It dives down into the two subtrees (temp->left and temp->right) and repeats the operation until it reaches nodes without children. at that point it will call maxDepth on left and right, which will be null and return 0, and then start returning back up the chain of calls.
So if you you have a chain of three nodes (say, root-left1-left2) it will get down to left2 and call maxDepth(left) and maxDepth(right). each of those return 0 (they are null). then it is back at left2. it compares, both are 0, so the greater of the two is of course 0. it returns 0+1. then we are at left1 - repeats, finds that 1 is the greater of its left n right (perhaps they are the same or it has no right child) so it returns 1+1. now we are at root, same thing, it returns 2+1 = 3, which is the depth.
Because the depth is calculated with previous node+1
To find Maximum depth in binary tree keep going left and Traveres the tree, basically perform a DFS
or
We can find the depth of the binary search tree in three different recursive ways
– using instance variables to record current depth and total depth at every level
– without using instance variables in top-bottom approach
– without using instance variables in bottom-up approach
The code snippet can be reduced to just:
int maxDepth(Node *root){
if(root){ return 1 + max( maxDepth(root->left), maxDepth(root->right)); }
return 0;
}
A good way of looking at this code is from the top down:
What would happen if the BST had no nodes? We would have root = NULL and the function would immediately return an expected depth of 0.
Now suppose the tree was populated with a number of nodes. Starting at the top, the if condition would be true for the root node. We then ask, what is the max depth of the LEFT SUB TREE and the RIGHT SUB TREE by passing the root of those sub trees to maxDepth. Both the LST and the RST of the root are one level deeper than the root, so we must add one to get the depth of the tree at root of the tree passed to the function.
i think this is the right answer
int maxDepth(Node *root){
if(root){ return 1 + max( maxDepth(root->left), maxDepth(root->right)); }
return -1;
}

Binary tree where value of each node holds the sum of child nodes

This question was asked of me in an interview. How can we convert a BT such that every node in it has a value which is the sum of its child nodes?
Give each node an attached value. When you construct the tree, the value of a leaf is set; construct interior nodes to have the value leaf1.value + leaf2.value.
If you can change the values of the leaf nodes, then the operation has to go "back up" the tree updating the sum values.
This will be a lot easier if you either include back links in the nodes, or implement the tree as a "threaded tree".
Here is a solution that can help you: (the link explains it with tree-diagrams)
Convert an arbitrary Binary Tree to a tree that holds Children Sum Property
/* This function changes a tree to to hold children sum
property */
void convertTree(struct node* node)
{
int left_data = 0, right_data = 0, diff;
/* If tree is empty or it's a leaf node then
return true */
if(node == NULL ||
(node->left == NULL && node->right == NULL))
return;
else
{
/* convert left and right subtrees */
convertTree(node->left);
convertTree(node->right);
/* If left child is not present ten 0 is used
as data of left child */
if(node->left != NULL)
left_data = node->left->data;
/* If right child is not present ten 0 is used
as data of right child */
if(node->right != NULL)
right_data = node->right->data;
/* get the diff of node's data and children sum */
diff = left_data + right_data - node->data;
/* If node's data is smaller then increment node's data
by diff */
if(diff > 0)
node->data = node->data + diff;
/* THIS IS TRICKY --> If node's data is greater then increment left
subtree by diff */
if(diff < 0)
increment(node->left, -diff);
}
}
See the link to see the complete solution and explanation!
Well as Charlie pointed out, you can simply store the sum of respective subtree sizes in each inner node, and have leaves supply constant values at construction (or always implicitly use 1, if you're only interested in the number of leaves in a tree).
This is commonly known as an Augmented Search Tree.
What's interesting is that through this kind of augmentation, i.e., storing additional per-node data, you can derive other kinds of aggregate information for items in the tree as well. Any information you can express as a monoid you can store in an augmented tree, and for this, you'll need to specify:
the data type M; in your example, integers
a binary operation "op" to combine elements, with M op M -> M; in your example, the common "plus" operator
So besides subtree sizes, you can also express stuff like:
priorities (by way of the "min" or "max" operators), for efficient queries on min/max priorities;
rightmost elements in a subtree (i.e., an "op" operator that simply returns its second argument), provided that the elements you store in a tree are ordered somehow. Note that this allows us to view even regular search trees (aka. dictionaries -- "store this, retrieve that key") as augmented trees with a corresponding monoid.
(This concept is rather reminiscent of heaps, or more explicitly treaps, which store random priorities with inner nodes for probabilistic balancing. It's also quite commonly described in the context of Finger Trees, although these are not the same thing.)
If you also provide a neutral element for your monoid, you can then walk down such a monoid-augmented search tree to retrieve specific elements (e.g., "find me the 5th leaf" for your size example; "give me the leaf with the highest priority").
Uhm, anyways. Might have gotten carried away a bit there.. I just happen to find that topic quite interesting. :)
Here is the code for the sum problem. It works i have tested it.
int sum_of_left_n_right_nodes_4m_root(tree* local_tree){
int left_sum = 0;
int right_sum = 0;
if(NULL ==local_tree){
return 0;
}
if((NULL == local_tree->left)&&(NULL == local_tree->right)){
return 0;
}
sum_of_left_n_right_nodes(local_tree->left);
sum_of_left_n_right_nodes(local_tree->right);
if(NULL != local_tree->left)
left_sum = local_tree->left->data +
local_tree->left->sum;
if(NULL != local_tree->right)
right_sum = local_tree->right->data + \
local_tree->right->sum;
local_tree->sum= right_sum + left_sum;
}
With a recursive function you can do so by making the value of each node equal to the sum of the values of it's childs under condition that it has two children, or the value of it's single child if it has one child, and if it has no childs (leaf), then this is the breaking condition, the value never changes.