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.
Related
I keep getting the following error : Segmentation fault (core dumped) . I found out the line of code that is causing the problem ( marked with a comment inside of the program) . Please tell me why this error is happening and how to fix it.
I've tried to dry run my code (on paper ) and see no logical errors (from my understanding).
I have only recently got into coding and stackoverflow please guide me through how I can further improve my question , as well as my code . Thanks !
class tree
{
struct node // Creates a node for a tree
{
int data;
bool rbit,lbit; // rbit/lbit= defines if right/left child of root is present or not
node *left,*right;
};
public:
node *head,*root;
tree() // constructor initializes root and head
{
root=NULL;
head=createnode(10000);
}
node *createnode(int value)
{// Allocates memory for a node then initializes node with given value and returns that node
node *temp=new node ;
temp->data=value;
temp->lbit=0;
temp->rbit=0;
temp->left=NULL;
temp->right=NULL;
return temp;
}
void insert(node *temp,int value) // Creates binary search tree node by node
{
if(root==NULL) // Checking if tree is empty
{
root=createnode(value); //Root now points to new memory location
head->left=root;
head->lbit=1;
root->left=head;//this line gives the segmentation fault (what i thought before correction)
}
}
void inorder(node *root) // Inorder traversal of tree (this function is logically incorrect)
{
if(root==NULL)
return;
inorder(root->left);
cout<<root->data<<"\t";
inorder(root->right);
}
void getdata()//Accepts data , creates a node through insert() , displays result through inorder()
{
int data;
cout<<"Enter data"<<endl;
cin>>data;
insert(root,data);
inorder(root);
}
/*void inorder(node *root) // Working inorder code
{
if(root->lbit==1)
inorder(root->left);
cout<<root->data<<"\t";
if(root->rbit==1)
inorder(root->right);
}*/
};
int main()
{
tree t; // Tree Object
t.getdata(); // Calling getdata
return 0;
}
I think the comments section largely reflects a miscommunication. It's easy to believe that you are experiencing a crash ON that particular line.
This is not actually the case. Instead what you have done is created a loop in your tree which leads to infinite recursion by the inorder function. That causes a stack overflow which segfaults -- this would have been extremely easy to spot if you had just run your program with a debugger (such as gdb) attached.
temp = createnode(value);
if(root == NULL)
{
root = temp;
head->left = root;
head->lbit = 1;
temp->left = head;
}
Look at the loop you have just created:
head->left points to root
root->left == temp->left, which points to head
An inorder traversal will now visit:
root
head
root
head
root
head
...
Since it never gets to the end of the left-branch, the function never outputs anything before overflowing the stack and crashing.
So no, your code is not logically correct. There's a fundamental design flaw in it. You need to rethink what you are storing in your tree and why.
From the code,
root=temp; //Root now points to temp
head->left=root;
head->lbit=1;
temp->left=head;// this line gives the segmentation fault
root is not pointing to temp. temp(pointer) is assigned to root(pointer).
head's left pointer is root, and temp's left is head (which means root's left is head). so in the function "inorder",
void inorder(node *root) // Inorder traversal of tree
{
if(root==NULL) <<<<<<
return;
inorder(root->left);
cout<<root->data<<"\t";
inorder(root->right);
}
the argument node *root (left) is never NULL and the function never return.
There's not enough information on exactly how this should work (what is node.lbit for example).
The question's insert() function will not work. It's passing in a value which is immediately overwritten (among other issues). There's no explanation of what tree.head is for, so it's ignored. The fields node.lbit and node.rbit look to be superfluous flags of node.left != NULL (similarly for right). These are omitted too. The insert() is also not creating the tree properly.
void insert(int value) // Insert a value into the tree (at branch)
{
// Create a new node to insert
struct node *temp = createnode(value);
if (root == NULL) // Checking if tree is empty
{
root = temp; //Root now points to temp
}
else
{
insertAtBranch(root, temp);
}
}
// recursively find the leaf-node at which to insert the new node
void insertAtBranch(node *branch, node *new_node)
{
// to create a BST, less-than go left
if (new_node->value <= branch->value)
{
if (branch->left == NULL)
branch->left = new_node; // There's no left-branch, so it's the node
else
insertAtBranch(branch->left, new_node); // go deeper to find insertion point
}
else // greater-than go right
{
if (branch->right == NULL)
branch->right = new_node;
else
insertAtBranch(branch->right, new_node);
}
}
Imagine how a binary tree works. New nodes are only ever inserted at the edges. So you look at a given node, and decide if this new-node is less or grater than the one you're looking at (unless the tree is empty, of course).
Say the new-node.value is less than the branch-node.value, you want to branch left. Still with the same node, if it doesn't have a left-branch (node.left == NULL), the new node is the left branch. Otherwise you need to travel down the left-branch and check again.
I would have made node a class, and used a constructor to at least set the default properties and value. But that's not a big deal.
This is the standard algorithm for printing ancestors of a particular Node in a Binary Tree and it takes O(n) time complexity.
bool print(Node *node,int target){
if(node==NULL)
return false;
if(node->target==target)
return true;
if(print(node->left)||print(node->right)){
cout << node->data;
return true;
}
return false;
}
The question is if we need to print all ancestors of all node's and also store ancestors in an array for each node. what is the time complexity? Can we do it better than O(n^2) i.e without looping through each node and find ancestors.If possible how?
If you want an array corresponding to each node in the tree, then you cannot do better than O(N2) worst case, because the total size of all arrays is worst case O(N2) (in the case that every node in the tree has at most one child). If you expect the trees to be somewhat balanced, this reduces to O(N log N).
You can achieve O(N) construction by sharing data, using a linked list instead of an array for each node. In effect, that's equivalent to computing a parent link for each node, because the linked list is simply a traversal of parent links. But you cannot avoid the cost of printing, because you will print average O(N log N) / worst case O(N2) items when you print out all the ancestor chains.
The parent link construction algorithm is basically the same as the algorithm you present: recursively walk the tree setting the parent links of the children to the current node. To print the ancestor chains for each node, you can use the parent links while you walk the tree.
It can be done in O(n*h), where h is the tree's height, by implementing a DFS, that keeps track of currently open nodes.
A simple c++ like pseudo code can be something like:
void PrintAll(const Node& node) {
open = std::unordered_set<Node>; // empty hash set
PrintAll(node, &open);
}
void PrintAll(const Node& node, std::unordered_set* open) {
if (node == null)
return;
for (const Node& ancestor: open)
cout << ancestor<< "," << node;
open->add(node);
PrintAll(node.left, open);
PrintAll(node.right, open);
open->remove(node);
}
Caveat: In here, we do not print (node, node) (each node is also an ancestor of itself). If we want to do it, it can be fixed easily by adding the addition of node to open before the printing loop.
Also, you can make the unordered_set store only the data, rather than the entire node.
The following code will do the job :
Language Used : Java
// Algorithm for printing the ancestors of a Node.
static boolean findAncestors(Node root, Node a)
{
if(root==null)
{
return false;
}
else if(root==a)
{
System.out.print("Printing ancestors of node " + a.data + " : " + a.data);
return true;
}
else
{
boolean var=false;
var=findAncestors(root.left, a);
if(var)
{
System.out.print(", " + root.data);
return true;
}
var=findAncestors(root.right, a);
if(var)
{
System.out.print(", " + root.data);
return true;
}
}
return false;
}
im working on an implimentation of an AVL tree, and im having problems with my recalculate height function. When i call it i pass in the root of the tree and a variable that has a value of 1. ive stepped through it, and found that once it gets to the while loop it preforms as expected but after that it returns to just ones. can you please look at it and see what i am doing wrong. I will post more code if neede, but i think just the function will provide you with enough information. Thanks
void BinaryTree::recalculate(Node *leaf, int count)
{
if(leaf == NULL)//if we are at the root
{
return;//exit the function
}
if((leaf->getLeft() != NULL))//if we are not at the end of the subtree
{
recalculate(leaf->getLeft(), count);//advance to the next node and re-enter the function
}
if(leaf->getRight() != NULL)//if we are not at the end of the right subtree
{
recalculate(leaf->getRight(), count);//advance to the next node and re-enter the program
}
else
{
while(leaf->getParent() != NULL)//calculate each subtree until we are at the root
{
leaf = leaf->getParent();//get the parent node
count++;//increment the height
if(leaf->getLeft() != NULL)//if there is an item in the left
{
leaf->getLeft()->setHeight(count-1);//sets the hight of the left child
}
if(leaf->getRight() != NULL)//if there is an item in the right
{
leaf->getRight()->setHeight(count -1);//sets the height of the right child
}
}
return;//exit the function
}
}
Your function is supposed to compute the height of each subtree of a binary tree, and save that value in the root node of that subtree. You chose to follow a recursive approach, which is the standard one. In this approach, the height of both left and right subtree must be computed first, and then the highest of both is taken for the current node.
In your implementation, you use a value named count passed in parameter to the recursive call. What is the purpose of that value, given that we need to retrieve a count from subnodes, not pass one to them?
If you:
remove that value from the recalculate parameters
have the recalculate method call itself first on both children if applicable
make the recalculate update the current node height from each subnode height
you should have it working. The following is a possible implementation based on this algorithm:
void BinaryTree::recalculate(Node *leaf) {
int count = 0;
if (leaf == NULL) {
return;
}
if (leaf->getLeft() == NULL && leaf->getRight() == NULL) {
// no child, the height is 0
setHeight(0);
return;
}
if (leaf->getLeft() != NULL) {
recalculate(leaf->getLeft());
count = leaf->getLeft()->getHeight();
}
if (leaf->getRight() != NULL){
recalculate(leaf->getRight());
count = max(count, leaf->getRight()->getHeight());
}
// include leaf in the height
setHeight(count+1);
}
If the getHeight method cannot be used, you may replace it by having recalculate return the height it computed.
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.
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));
}
}