I am trying to calculate the height of a tree. I am doing it with the code written below.
#include<iostream.h>
struct tree
{
int data;
struct tree * left;
struct tree * right;
};
typedef struct tree tree;
class Tree
{
private:
int n;
int data;
int l,r;
public:
tree * Root;
Tree(int x)
{
n=x;
l=0;
r=0;
Root=NULL;
}
void create();
int height(tree * Height);
};
void Tree::create()
{
//Creting the tree structure
}
int Tree::height(tree * Height)
{
if(Height->left==NULL && Height->right==NULL)
{return 0;
}
else
{
l=height(Height->left);
r=height(Height->right);
if (l>r)
{l=l+1;
return l;
}
else
{
r=r+1;
return r;
}
}
}
int main()
{
Tree A(10);//Initializing 10 node Tree object
A.create();//Creating a 10 node tree
cout<<"The height of tree"<<A.height(A.Root);*/
}
It gives me the correct result.
But in some posts(googled page) it was suggested to do a Postorder traversal and use this height method to calculate the height. Any specific reason?
But isn't a postorder traversal precisely what you are doing? Assuming left and right are both non-null, you first do height(left), then height(right), and then some processing in the current node. That's postorder traversal according to me.
But I would write it like this:
int Tree::height(tree *node) {
if (!node) return -1;
return 1 + max(height(node->left), height(node->right));
}
Edit: depending on how you define tree height, the base case (for an empty tree) should be 0 or -1.
The code will fail in trees where at least one of the nodes has only one child:
// code snippet (space condensed for brevity)
int Tree::height(tree * Height) {
if(Height->left==NULL && Height->right==NULL) { return 0; }
else {
l=height(Height->left);
r=height(Height->right);
//...
If the tree has two nodes (the root and either a left or right child) calling the method on the root will not fulfill the first condition (at least one of the subtrees is non-empty) and it will call recursively on both children. One of them is null, but still it will dereference the null pointer to perform the if.
A correct solution is the one posted by Hans here. At any rate you have to choose what your method invariants are: either you allow calls where the argument is null and you handle that gracefully or else you require the argument to be non-null and guarantee that you do not call the method with null pointers.
The first case is safer if you do not control all entry points (the method is public as in your code) since you cannot guarantee that external code will not pass null pointers. The second solution (changing the signature to reference, and making it a member method of the tree class) could be cleaner (or not) if you can control all entry points.
The height of the tree doesn't change with the traversal. It remains constant. It's the sequence of the nodes that change depending on the traversal.
Definitions from wikipedia.
Preorder (depth-first):
Visit the root.
Traverse the left subtree.
Traverse the right subtree.
Inorder (symmetrical):
Traverse the left subtree.
Visit the root.
Traverse the right subtree.
Postorder:
Traverse the left subtree.
Traverse the right subtree.
Visit the root.
"Visit" in the definitions means "calculate height of node". Which in your case is either zero (both left and right are null) or 1 + combined height of children.
In your implementation, the traversal order doesn't matter, it would give the same results. Cant really tell you anything more than that without a link to your source stating postorder is to prefer.
Here is answer :
int Help :: heightTree (node *nodeptr)
{
if (!nodeptr)
return 0;
else
{
return 1 + max (heightTree (nodeptr->left), heightTree (nodeptr->right));
}
}
Related
I am trying to traverse a binary tree built with the input data from keyboard. Data is inserted to the binary tree successfully. I have a switch statement, where 'case 4' should traverse (and print) the binary tree level by level. However I got EXC_BAD_ACCESS error. I would be more than happy if someone help me out with this one.
(RootPtr is the top -Level 0- node of the binary tree defined globally; TreeDepth() is the function calculating "Depth" of the tree where Depth defined globally and root node has depth of 0; and GetNode is basically an initializer function (using malloc) for type TreePtr pointers.)
Thank you all in advance.
Here is the relevant code:
This is the struct definition;
typedef struct treeItem
{
int data;
struct treeItem *left;
struct treeItem *right;
}Tree , *TreePtr;
This is the switch case where I call Level by Level traversing function(s);
case 4:
TreePtr temp;
GetNode(&temp);
temp = RootPtr;
printLevelOrder(temp);
printf("\n\n");
break;
These are the functions used for traversing the tree level by level;
void printGivenLevel(TreePtr TemPtr, int level)
{
if (items == 0)
return;
else
{ if(level == 0 )
{
printf(" %d", (*TemPtr).data); //the line I got ERROR
}
else
{
printGivenLevel((*TemPtr).left, (level-1));
printGivenLevel((*TemPtr).right, (level-1));
}
}
}
void printLevelOrder(TreePtr TemPtr)
{
TreeDepth();
if (items == 0)
printf("\nTree is empty.\n");
else
{
printf("Traverse level by level:");
for (int i=0; i<=Depth; i++)
{
printGivenLevel(TemPtr, i);
}
}
}
It's an off by one error. In your for loop:
for (int i=0; i<=Depth; i++)
You're traversing this loop Depth + 1 times. This means you're trying to access one more level than there actually is. In particular, in the final call of printGivenLevel, in the point in the recursion where level == 1, you're already at the bottom of the tree. You're now recursing one more time, but the pointers you pass into the next recursion level are garbage pointers (they aren't guaranteed to point to memory you're allowed to access, or even exists). So when you try to dereference them, you get an error.
One more thing: this implementation is pretty inefficient, since you're traversing the tree many times. It's better to do a breadth-first search, like kiss-o-matic mentioned. This way, you'll only traverse the tree once, which is much faster (although it does use more memory).
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.
I am in the process of implementing a Binary Search tree that gets represented using the Array implementation. This is my code so far: Take note that I have done with the Structure of tree and it is being saved as a Linked List. I want to convert this linked list into an array.
My thoughts on how to go about this are as followed. Make a return_array function. Have the Size of the array set to the Max number of nodes( 2^(n-1)+1) and go through the linked list. Root node would be # position 0 on the array then his L-child = (2*[index_of_parent]+1) and R-child = (2*[index_of_parent]+2). I looked around for a bit and searched to find something that can get me an idea of how I can keep track of each node and how I can go through each one.
Am I overthinking this problem?
Can there be a Recursion?
Also, I'm considering creating a visual tree instead of an array but have no idea how to space it out correctly. If anyone has an idea on how to do that it would be awesome to get a better understanding of that.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cmath>
using namespace std;
struct node {
int data;
struct node* left;
struct node* right;
};
void inorder(struct node* node){
if(node){
inorder(node->left);
cout << node->data << " ";
inorder(node->right);
}
}
void insert(struct node** node, int key){
if(*node == NULL){
(*node) = (struct node*)malloc(sizeof(struct node));
(*node)->data = key;
(*node)->left = NULL;
(*node)->right = NULL;
printf("inserted node with data %d\n", (*node)->data);
}
else if ((*node)->data > key){
insert((&(*node)->left),key);
}
else
insert((&(*node)->right),key);
}
int max_tree(struct node* node){
int left,right;
if(node == NULL)
return 0;
else
{
left=max_tree(node->left);
right=max_tree(node->right);
if(left>right)
return left+1;
else
return right+1;
}
}
//This is where i dont know how to keep the parent/children the array.
void return_array(struct node* node, int height){
int max;
height = height - 1;
max = pow(2, height) - 1;
int arr [height];
}
int main(){
int h;
struct node* root = NULL;
insert(&root, 10);
insert(&root, 20);
insert(&root, 5);
insert(&root, 2);
inorder(root);
cout << endl;
cout << "Height is: ";
cout << max_tree(root);
h = max_tree(root)
return_array(root, h)
}
Considering that you want to efficiently store a binary search tree, using
l = 2i + 1
r = 2i + 2
will waste space every time your tree encounters a leaf node that is not occurring at the end of the tree (breadth-first). Consider the following simple example:
2
/ \
1 4
/ \
3 5
This (when transformed breadth-first into an array) results in
[ 2, 1, 4, -, -, 3, 5 ]
And wastes two slots in the array.
Now if you want to store the same tree in an array without wasting space, just transform it into an array depth-first:
[ 2 1 4 3 5 ]
To recover the original tree from this, follow these steps for each node:
Choose the first node as root
For each node (including root), choose
a) the left child as the next smaller key from the array after the current key
b) the right child as the next bigger key from the array, being no larger than the smallest parent key encountered when last branching left, and smaller than the direct parent's key when you are currently in it's left branch
Obviously finding the correct b) is slightly more complex, but not too much. Refer to my code example here.
If I'm not mistaken, transforming to and from an array will take O(n) in either case. And as no space is wasted, space complexity is also O(n).
This works because binary search trees have more structure than ordinary binary trees; here, I'm just using the binary search tree property of the left child being smaller, and the right child being larger than the current node's key.
EDIT:
After doing some further research on the topic, I found that reconstructing the tree in preorder traversal order is much simpler. The recursive function doing that is implemented here and here, respectively.
It basically consists of these steps:
As long as the input array has unseen entries,
If the value to insert is greater than the current branch's minimum value and less than the current branch's maximum allowed,
Add a node to the tree at the current position and set it's value to the current input value
Remove current value from input
If there are items left in the input,
Recurse into the left child
Recurse into the right child
The current minimum and maximum values are defined by the position inside the tree (left child: less than parent, right child: greater than parent).
For more elaborate details, please refer to my source code links.
If you want to store the tree node in a array,you had better to start from 1 position of your array!So the relation between the parent and its children should be simple:
parent = n;
left = 2n;
right = 2n + 1;
you should BFS the tree,and store the node in the array(If the node is null you should also store in the array using a flag ex 0),you should get the very array of the tree!
To do this you have to follow these steps.
Create an empty queue.
Make the first node of the list as root, and enqueue it to the queue.
Until we reach the end of the list, do the following.
a. Dequeue one node from the queue. This is the current parent.
b. Traverse two nodes in the list, add them as children of the current parent.
c. Enqueue the two nodes into the queue.
Time Complexity: Time complexity of the above solution is O(n) where n is the number of nodes.
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.
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.