using a stack to get the height of a BST - c++

I am trying to get the height of a BST using a stack. I was told that I should use preorder and measure find the largest size of the stack. However, this does not seem to work. Any ideas of what I am doing wrong.
int PBT::maxDepth() {
if (!root) {
return -1;
}
int depth=0;
stack<TreeNode *>s;
TreeNode * nodePtr=root;
for (; ; ) {
while (nodePtr) {
s.push(nodePtr);
if (s.size() > depth)
depth = s.size();
nodePtr=nodePtr->left;
}if (s.empty()) {
break;
}
nodePtr=s.top();
s.pop();
nodePtr=nodePtr->right;
}
return depth;
}

The stack size is incorrect value of depth for some nodes. Eg. if the current node is a right child of other node, the stack doesn't contain this other node (our parent). For the rightest node in the tree, the stack will have no items.
You'll have to calculate the depth correctly. In your case, you may go up more levels in one pop, so subtracting one won't work, but if you save your current depth to the stack (and restore it while popping), it will work.
To do that, you should change your stack definition to eg.
stack<pair<TreeNode*, unsigned> > stack;
and add a variable current_depth.
For each "nodePtr=nodeptr->left/right", you increment current_depth. Push with
s.push(make_pair(nodeptr, current_depth));
and before you pop, restore current_depth with
current_depth = s.top().second;
(The node pointer is obviously in .first)

Related

where is the faulty logic in this re-heap function?

I'm currently working with a heap structure which is suppose to be used to sort numbers in an array. I have done something like this in the code when I want to sort the structure when I pop(dequeue) a element from the heap.
template<typename T>
inline void dHeap<T>::reHeapDown(int root, int bottom)
{
int minChild;
int rightChild;
int leftChild;
int temp;
// Get index of root's right/left child
leftChild = root * 2 + 1;
rightChild = root * 2 + 2;
//Then we are not done with re-heaping
if (leftChild <= bottom)
{
if (leftChild == bottom)
{
minChild = leftChild;
}
else
{
if (arr[leftChild] <= arr[rightChild])
minChild = leftChild;
else
minChild = rightChild;
}
if (arr[root] > arr[minChild])
{
// Swap these two elements
temp = arr[root];
arr[root] = arr[minChild];
arr[minChild] = temp;
// Make recursive call till reheaping completed
reHeapDown(minChild, bottom);
}
}
}
My thought here is that the lowest value in the heap always will be in the root and that's the value that I will be poped(dequeued) in my pop function.
But I'm having some problem that it wont sort the heap correctly.
is there something wrong with my logic in this function and if so, where is it?
Building a heap only enforces the property:
in case of min heap every parent is lesser than it children
in case of max heap every parent is greater than its children.
in case of min-max heap even depth levels (0,2,4..) are lesserr and odd levels (1,3,5...) are greater than their respective children.
However the heap will not necessarily be sorted. It will be balanced, because it is filled in order, level by level, from left to right.
Heapsort will sort an array by using heap functions. The final array will also work as a balanced and sorted heap.

how to get the max path cost in binary tree

how to get the max path cost in binary tree,
and print a vector includes all the path data elements?
i know how to get cost but dont know how to get the elements vector
any help?
struct Node
{
int data;
Node* left;
Node* right;
};
int treeMaxPath(Node* root) {
if (root== NULL)
return 0;
else
return root->data + max(treeMaxPath(root->left), treeMaxPath(root->right));
}
Bottom up process the tree, store the data += max subtrees.
Start at the top and print the value which is now (data - max subtrees) and then print the max child.
Go top down and restore data values, data -= max subtrees.
Notes:
This is O(N) time complexity and O(1) for memory.
Could be changed to store max without modifying data by adding a new variable to Node.
It can easily be modified to print all the max paths in the tree.
int maxChild(const Node *root) {
return max(root->left ? root->left.data : 0,
root->right ? root->right.data : 0);
}
void treeBottomUp(Node* root) {
if (root) {
treeBottomUp(root->left);
treeBottomUp(root->right);
root->data += maxChild(root);
}
}
void treeRestore(Node *root) {
if (root) {
root->data -= maxChild(root);
treeRestore(root->left);
treeRestore(root->right);
}
}
void printMaxPath(const Node* root) {
if (root) {
printf("%d\n", root->data - maxChild(root));
if (root->left && root->left.data >= maxChild(root)) {
printMaxPath(root->left);
} else {
printMaxPath(root->right);
}
}
}
And to do it all:
void solveTree(Node *root) {
treeBottomUp(root);
printMaxPath(root);
treeRestore(root);
}
Return a pair of cost and path. The path can be stored in vector<Node*>.
After completion of call to treeMaxPath for the whole tree (recursive call should complete for the whole tree if you invoke it on the root) you will have the whole tree updated with their depth values.
Now you can easily do a small tracking with a simple loop to traverse from root of the tree along the highest depth values till NULL child is met.
p.s. I'm not sure whether your implementation of treeMaxPath is correct. If the data that you store at a certain node is depth, some parts of your algorithm should be changed.

AVL Tree Rebalancing in C++

I'm working on an AVL tree. I think I've got all of the rotate functions working correctly. I have a rotateleft, rotateright, rotateleftright, and rotaterightleft function. They all take a node as a parameter.I don't know what node to pass to those parameters. Can you take a look at my AVL tree rebalance function and tell me if I have it correct, and what I need to pass to each of these functions. So far, I have the root or the top node, but i think I'm wrong. How do I tell what I need to pass to these functions?
Here is the function:
void BinaryTree::rebalance(Node *N)
{
int count = 1;
if((N->getLeft()->getHeight()) > (N->getRight()->getHeight() + 1))
{
if(N->getLeft()->getLeft()->getHeight() > N->getLeft()->getRight()->getHeight())
{
rotateRight(root);
recalculate(root, count);
}
else
{
rotateLeftRight(root);
recalculate(root, count);
}
}
else if(N->getRight()->getHeight()> N->getLeft()->getHeight() + 1)
{
if(N->getRight()->getRight()->getHeight() > N->getRight()->getLeft()->getHeight())
{
rotateLeft(root);
recalculate(root, count);
}
else
{
rotateRightLeft(root);
recalculate(root, count);
}
}
}
here is my rotate leftright
Node* BinaryTree::rotateLeftRight(Node *N)
{
Node *newNode = new Node();//declares a new Node
newNode = N->getLeft();//sets the node
N->setLeft(rotateLeft(newNode->getLeft());//sets the left subtree
recalculate(root);//recalculates the height
root->setHeight(NULL);//sets the height of the root node
return rotateRight(N);//retuns the tree rotated right
}
and here is my rotate left function.:
Node* BinaryTree::rotateLeft(Node *N)
{
Node *newNode = new Node();//declares a new node
newNode = N->getRight();//sets the new node to the right child of N
N->setRight(newNode->getLeft());//sets the right of N equal to new nodes left child
newNode->setLeft(N);//sets the left child of the new node to N
return newNode;//retuns the newNode
}
if i have the tree 50 20 10 and 15 what do i pass to the each of these functions to rebalance the tree?
There are some errors in your code that you did not do in the one you submitted in another question, that is you don't check for nullary pointers in your code:
you don't check if N is NULL at the begining of the method
you don't check in the line below (and in its symmetrical sibling) if the left and right nodes are NULL
if((N->getLeft()->getHeight()) > (N->getRight()->getHeight() + 1))
Regarding the algorithm itself, it depends on the behaviour of the rotation functions. The algorithm as described in the wikipedia entry explains that the second case in your nested if (the rotateLeftRight and rotateRightLeft methods) should perform 2 rotations. If your rotation functions are conform to that description, you should be alright.
The case of recalculate has been taken care of in an other question, but in this situation, you actually don't need to recalculate the height for the whole subtree, as you correctly told me in comments in that question. The only changing nodes are the ones whose children have been changed. You should perform that computation within each specific rotation method, since each case describe exactly which nodes get updated.

Binary tree stack overflow

I have made a binary tree based on Alex Allain's example found here. It throws a stack overflow exception after adding about 5000-6000 elements to it. Any idea of how to prevent a stack overflow? The cause is that Insert() calls itself recursivly.
Update 3/6/2013
Here is how I refactored the code to avoid stack overflow:
void Insert(Key_T key, Value_T val, QuickMapNode<Key_T, Value_T> *leaf)
{
while (true)
if(key < leaf->key)
{
if(leaf->left) leaf = leaf->left;
else
{
leaf->left = new QuickMapNode<Key_T, Value_T>;
leaf->left->key = key;
leaf->left->val = val;
leaf->left->parent = leaf;
leaf->left->left = NULL; // Sets the left child of the child node to null
leaf->left->right = NULL; // Sets the right child of the child node to null
break;
}
}
else if (key >= leaf->key)
{
if(leaf->right) leaf = leaf->right;
else
{
leaf->right = new QuickMapNode<Key_T, Value_T>;
leaf->right->key = key;
leaf->right->val = val;
leaf->right->parent = leaf;
leaf->right->left = NULL; // Sets the left child of the child node to null
leaf->right->right = NULL; // Sets the right child of the child node to null
break;
}
}
}
Like Öö Tiib said, you should change insert to be not recursive. Every recursive function can be turned into a non-recursive one by storing the data that would go on the stack in some other data structure. This way you can use the heap for those data and don't have the overhead of function calls on the stack (return address etc.) You can often use a vector or list that you use like a stack: take (and pop) the back() of the vector to get the current argument, and in places your current code would recursively call itself, you push_back() what you would have passed to the recursive function call.
Here's the insert() method from your link as an iterative version:
void btree::insert(int key, node *leaf)
{
std::list<node*> leafs;
leafs.push_back(leaf);
while (leafs.size() > 0)
{
leaf = leafs.back();
leafs.pop_back();
if(key < leaf->key_value)
{
if(leaf->left!=NULL)
leafs.push_back(leaf->left);
else
{
leaf->left=new node;
leaf->left->key_value=key;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else if(key>=leaf->key_value)
{
if(leaf->right!=NULL)
leafs.push_back(leaf->right);
else
{
leaf->right=new node;
leaf->right->key_value=key;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
}
}
I ran the code and it seems to work. It's much slower than the recursive version though, not sure why that is ... Both versions work fine with 10000 and more elements, so there's perhaps something else wrong in your implementation ...
Actually, when traversing a binary tree like we do here, there's no need to store any previous information, as we don't do any backtracking. Once the location for the new element is found, we're finished. So we can get rid of the list/vector altogether:
void btree::insert(int key, node *leaf)
{
while (leaf != NULL)
{
if(key < leaf->key_value)
{
if(leaf->left!=NULL)
leaf = leaf->left;
else
{
leaf->left=new node;
leaf->left->key_value=key;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
return;
}
}
else if(key>=leaf->key_value)
{
if(leaf->right!=NULL)
leaf = leaf->right;
else
{
leaf->right=new node;
leaf->right->key_value=key;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
return;
}
}
}
}
Make algorithm of insert that is not recursive. You do need only to search place where to insert so you do not need stack of calls for that.
Taking guesses due to lack of provided details: assume worst case, that after 6000 inserts the stack depth is all 6000 recursive calls. Assume a reasonable stack frame size of maybe 20 bytes - then stack size is 6000 * 20 = 120,000 bytes. If the stack frame is actually 160 bytes (8x larger) then the stak size is 6000 * 160, slightly less than 1MB. I wonder ... is there a limit on your number of elements? What is the allocated stack size?
The comments above tell you how to actually solve the problem (balanced tree). I might add, just about any recursive algorithm can be converted to an iterative algorithm - it isn't as elegant and it will take effort to get it right, but then you won't fill up the stack. But if there really is (not just you think there is) a limit on the number of input elements, then it seems to me you could determine the size of the stack frame for insert and make the stack size large enough to fit #elements * stack frame size, the worst case, plus a little more for whatever extra is on the stack.
As mentioned above the most likely cause is the stack overflow due to too many recursive insert calls
The following are the different options
Use a self balancing tree http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree
Use a non recursive tree decent algorithmn.Lookk at this example Non-recursive add function in a binary tree using c++

Binary tree Basics in C++

I have a binary tree data structure of:
//Declare Data Structure
struct CP {
int id; //ID of the Node
int data; //Data of the Node
CP * left; //Pointer to the Left Subtree
CP * right; //Pointer to the Right Subtree
};
typedef CP * CPPtr;
Without changing the tree structure, how do I actually calculate the depth if given a node id. (id is a unique indicator to each tree node)
your code is lack of some base steps or necessary initializations.
BTree_Helper(BTree *Tree){// this is roughly written like pseudo code
if(TLeft == NULL && TRight == NULL){
depth of tree = 0 ;
}
else if (TLeft == NULL){
depth of tree = depth of right tree ;
}
else if(TRight==NULL){
depth of tree = depth of left tree;
}
else{
depth of tree = the maximum between depth of left and depth of right;
}
}
I just gave some hints for your convinence.
Think carefully and try as many test suites as possible.
Going off of what y26jin suggested, maybe something like this?
BTree_Helper(CP *TreeNode) {
CP *TLeft = TreeNode->left;
CP *TRight = TreeNode->right;
if(TLeft == NULL && TRight == NULL){
return 0;
}
else if (TLeft == NULL){
return 1+(BTree_Helper(TRight));
}
else if(TRight==NULL){
return 1+(BTree_Helper(TLeft));
}
else{
return 1+max(BTree_Helper(TLeft),BTree_Helper(TRight));
}
}
I can't actually test the code right now, sorry if I'm way off here. But I think something along these lines should work.
I'm going to assume that id is the search key for the tree. In other words, the id of any node on the left subtree is less than the id of this node, and the id of any node on the right subtree is greater than the id of this node. Also, id is assumed to be unique.
To find a node with a given ID, given a pointer to the root node of the tree, you just do:
CP* find(CP* root, int searchID)
{
// Starting point.
CP* node = root;
while(node)
{
// Search hit?
if(node->id == searchID)
return node;
// Turn left or right?
if(node->id < searchID)
node = node->left;
else
node = node->right;
}
return 0; // No node with the given ID found.
}
Finding depth is a simple modification of this function: instead of returning a node, you keep count of how many levels you descend. A depth of 0 means the root node is what you want; a depth of 1 means either the left or right nodes; a depth of 2 means any of their direct children, etc. So it's really how many times you have to loop:
int depth(CP* root, int searchID)
{
// Starting point.
CP* node = root;
int depth = 0;
while(node)
{
// Search hit?
if(node->id == searchID)
return depth;
// Descending a level...
++depth;
// Turn left or right?
if(node->id < searchID)
node = node->left;
else
node = node->right;
}
return -1; // No node with the given ID found.
}
Note the special value -1 for "not found".
I recommend storing the depth of a node's subtree in that node. Then you can just update the depth of the tree as you add nodes to it. Whenever you add a node, back out of the tree, updating the depth of each node along the path to the root on the way out. If at any point, the new depth of a node's modified subtree is not greater than the depth of the node's other subtree, you can short-circuit.
The benefits to this approach are:
It's worst-case performance is O(log n) (assuming that the tree is balanced).
It is extremely easy to write non-recursively
Read about basic tree/graph search algorithms: breadth-first search (BFS) and depth-first search (DFS). Try implementing DFS both recursively and with an explicit stack<T>. Implement BFS using a queue<T>.
Pay attention to the efficiency of your approach. If you want to look-up the depth of nodes repeatedly it will probably be much faster to store the depth of every node in the tree in some sort of look-up table. Ideally a hash table but a map<T1, T2> will do in most cases.
You'll learn a lot from the above exercises. Good luck!
You can calculate the depth from any node using recursion:
int countChildren(CPPtr node) {
if ( node != null )
return 1 + countChildren(node->left) + countChildren(node->right);
else
return 0;
}
You have to pass pointers to lDepth and rDepth, not the values themselves, like so:
nodeDepth_Helper(tree,id, &lDepth, &rDepth);
Furthermore, I think the arguments to nodeDepth_helper should be declared as pointers to ints:
void nodeDepth_Helper(CPPtr tree, int id, int* lDepth,int* rDepth)
making these changes throughout should fix your problem.