Path of the diameter of a binary tree - c++

I have a binary tree and a method for the size of the longest path (the diameter):
int diameter(struct node * tree)
{
if (tree == 0)
return 0;
int lheight = height(tree->left);
int rheight = height(tree->right);
int ldiameter = diameter(tree->left);
int rdiameter = diameter(tree->right);
return max(lheight + rheight + 1, max(ldiameter, rdiameter));
}
I want the function to return also the exact path (list of all the nodes of the diameter).
How can I do it?
Thanks

You have two options:
A) Think.
B) Search. Among the first few google hits you can find this: http://login2win.blogspot.hu/2012/07/print-longest-path-in-binary-tree.html
Choose A) if you want to learn, choose B) if you do not care, only want a quick, albeit not necessarily perfect solution.
There are many possible solutions, some of them:
In a divide and conquer approach you will probably end up with maintaining the so far longest paths on both sides, and keep only the longer.
The quoted solution does two traversals, one for determining the diameter, and the second for printing. This is a nice trick to overcome the problem of not knowing whether we are at the deepest point in approach 1.
Instead of a depth first search, do a breadth first one. Use a queue. Proceed level by level, for each node storing the parent. When you reach the last level (no children added to queue), you can print the whole path easily, because the last printed node is on (one) longest path, and you have the parent links.

Add a property struct node * next to the node struct. Before the return statement, add a line like this tree->next = (ldiameter > rdiameter ? tree->left : tree->right) to get the longer path node as the next node. After calling diameter(root), you should be able to iterate through all of the next nodes from the root to print the largest path.

I think the following may work... compute the diameter as follows in O(N) time.
// this is a c++ code
int findDiameter(node *root, int &max_length, node* &max_dia_node, int parent[], node* parent_of_root){
if(!root) return 0;
parent[root->val] = parent_of_root->val;
int left = findDiameter(root->left, max_length);
int right = findDiameter(root->right, max_length);
if(left+right+1 > max_length){
max_dia_node = root;
max_length = left+right+1;
}
return 1 + max(left,right);
}
So in this function number of things is happening. First max_length is calculating the max diameter of the tree. And along with that I am assigning the max_dia_node to this node.
This is the node through which I will have my max diameter pass through.
Now using this information we can find the max depth left child and right child of this node (max_dia_node). From that we can have the actual nodes via "parent" array.
This is two traversal of the tree.

Related

Maximum number of left nodes/children in a path

I am trying to find a way to output the amount of most left nodes found in a path.
For example:
The max nodes in this Binary Search Tree would be 2 (Goes from 5 ->3->1 and excluding the root).
What is the best way to approach this?
I have seen this thread which is fairly similar to what I am trying to achieve.
Count number of left nodes in BST
but there is like one line in the code that I don't understand.
count += countLeftNodes(overallRoot.left, count++);
overallRoot.left
My guess is that it calls a function on the object, but I can't figure out what goes into that function and what it would return.
Any answers to these two questions would be appreciated.
The answer you linked shows how to traverse the tree, but you need a different algorithm to get your count, since as you have noted, that question is trying to solve a slightly different problem.
At any given point in the traversal, you will have the current left count: this will be passed down the tree as a second parameter to countLeftNodes(). That starts with zero at the root, and is increased by one whenever you go into the left child of a node, but is set to zero when you enter the right node.
Then for both the left and right traversals, you set the left count to the greater of its current value, and the return from the recursive call to countLeftNodes(). And then this final value is what you return from countLeftNodes()
Here's a shot at the algorithm #dgnuff illustrated:
void maxLeftNodesInPath(Node *root, int count, int *best) {
if (root) {
maxLeftNodesInPath(root->left, ++count, best);
maxLeftNodesInPath(root->right, 0, best);
}
else if (count > *best) {
*best = count - 1;
}
}
The explanation is pretty much the same: keep accumulating on a count while traversing left, reset when moving to a right child, and if at a leaf, update the best.

Segmentation fault in recursive function when using smart pointers

I get a segmentation fault in the call to
auto n1=std::make_shared<Node>(n,n->x+i,n->y+j);
after a few recursive calls. Strange thing is that it's always at the same point in time. Can anyone spot the problem?
This is an implementation for a dynamic programming problem and here I'm accumulating the costs of a path. I have simplified the cost function but in this example the problem still occurs.
void HorizonLineDetector::dp(std::shared_ptr<Node> n)
{
n->cost= 1 + n->prev->cost;
//Check if we reached the last column(done!)
if (n->x==current_edges.cols-1)
{
//Save the info in the last node if it's the cheapest path
if (last_node->cost > n->cost)
{
last_node->cost=n->cost;
last_node->prev=n;
}
}
else
{
//Check for neighboring pixels to see if they are edges, launch dp with all the ones that are
for (int i=0;i<2;i++)
{
for (int j=-1;j<2;j++)
{
if (i==0 && j==0) continue;
if (n->x+i >= current_edges.cols || n->x+i < 0 ||
n->y+j >= current_edges.rows || n->y+j < 0) continue;
if (current_edges.at<char>(n->y+j,n->x+i)!=0)
{
auto n1=std::make_shared<Node>(n,n->x+i,n->y+j);
//n->next.push_back(n1);
nlist.push_back(n1);
dp(n1);
}
}
}
}
}
class Node
{
public:
Node(){}
Node(std::shared_ptr<Node> p,int x_,int y_){prev=p;x=x_;y=y_;lost=0;}
Node(Node &n1){x=n1.x;y=n1.y;cost=n1.cost;lost=n1.lost;prev=n1.prev;}//next=n1.next;}
std::shared_ptr<Node> prev; //Previous and next nodes
int cost; //Total cost until now
int lost; //Number of steps taken without a clear path
int x,y;
Node& operator=(const Node &n1){x=n1.x;y=n1.y;cost=n1.cost;lost=n1.lost;prev=n1.prev;}//next=n1.next;}
Node& operator=(Node &&n1){x=n1.x;y=n1.y;cost=n1.cost;lost=n1.lost;prev=n1.prev;n1.prev=nullptr;}//next=n1.next;n1.next.clear();}
};
Your code looks like a pathological path search, in that it checks almost every path and doesn't keep track of paths it has already checked you can get to more than one way.
This will build recursive depth equal to the length of the longest path, and then the next longest path, and ... down to the shortest one. Ie, something like O(# of pixels) depth.
This is bad. And, as call stack depth is limited, will crash you.
The easy solution is to modify dp into dp_internal, and have dp_internal return a vector of nodes to process next. Then write dp, which calls dp_internal and repeats on its return value.
std::vector<std::shared_ptr<Node>>
HorizonLineDetector::dp_internal(std::shared_ptr<Node> n)
{
std::vector<std::shared_ptr<Node>> retval;
...
if (current_edges.at<char>(n->y+j,n->x+i)!=0)
{
auto n1=std::make_shared<Node>(n,n->x+i,n->y+j);
//n->next.push_back(n1);
nlist.push_back(n1);
retval.push_back(n1);
}
...
return retval;
}
then dp becomes:
void HorizonLineDetector::dp(std::shared_ptr<Node> n)
{
std::vector<std::shared_ptr<Node>> nodes={n};
while (!nodes.empty()) {
auto node = nodes.back();
nodes.pop_back();
auto new_nodes = dp_internal(node);
nodes.insert(nodes.end(), new_nodes.begin(), new_nodes.end());
}
}
but (A) this will probably just crash when the number of queued-up nodes gets ridiculously large, and (B) this just patches over the recursion-causes-crash, doesn't make your algorithm suck less.
Use A*.
This involves keeping track of which nodes you have visited and what nodes to process next with their current path cost.
You then use heuristics to figure out which of the ones to process next you should check first. If you are on a grid of some sort, the heuristic is to use the shortest possible distance if nothing was in the way.
Add the cost to get to the node-to-process, plus the heuristic distance from that node to the destination. Find the node-to-process that has the least total. Process that one: you mark it as visited, and add all of its adjacent nodes to the list of nodes to process.
Never add a node to the list of nodes to process that you have already visited (as that is redundant work).
Once you have a solution, prune the list of nodes to process against any node whose current path value is greater than or equal to your solution. If you know your heuristic is a strong one (that it is impossible to get to the destination faster), you can even prune based off of the total of heuristic and current cost. Similarly, don't add to the list of nodes to process if it would be pruned by this paragraph.
The result is that your algorithm searches in a relatively strait line towards the target, and then expands outwards trying to find a way around any barriers. If there is a relatively direct route, it is used and the rest of the universe isn't even touched.
There are many optimizations on A* you can do, and even alternative solutions that don't rely on heuristics. But start with A*.

Binary Search tree Array implementation C++

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.

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.

Inserting into an Array Based Binary Search Tree? C++

Im trying to insert into an array Based Binary Search tree.
I am not sure how i prevent overwriting data using left and right indexes...
Do i insert leftchild as tree[2 * i + 1] and rightchild as tree[2 * i + 2] ? I think it is for locating the position of a node given its name...
Thats my problem. Not knowing how to insert, recursively or iteratively(ive chosen recursively but it might be totally wrong).
BST::BST(int capacity) : items(new item[capacity]), size(0),
leftChild(0), rightChild(0), root_index(1)
{
items->empty = true;
maxSize = capacity-1;
}
Below is the insertion function. I have seen many that deal with Linked Lists implementations, But nothing array based! Here is my attempt:
void BST::insert(const data& aData)
{
if ( items[root_index].empty )
{
items[root_index].theData = aData;// Get the data.
items[root_index].empty = false;
oldRoot.theData = aData;
}
else
{
if ( aData < items[root_index].theData )
{
leftChild = root_index * 2;
if ( items[leftChild].empty )
{
items[leftChild].theData = aData;
items[leftChild].empty = false;
}//items->empty = true;
else
{
items[root_index].theData = items[leftChild].theData;
this->insert(aData);
}
}
else if ( items[root_index].theData < aData )
{
rightChild = root_index * 2 + 1;
if ( items[rightChild].empty )
{
items[rightChild].theData = aData;
items[rightChild].empty = false;
}
else//items->empty = true;
{
items[root_index].theData = items[rightChild].theData;
this->insert(aData);
}
}
else return;
}
items[1].theData = oldRoot.theData;
}
What is correct?...Does anyone have any array based suggstions for inserting? I appear to be stuck in an infinite recursion
First have a look at what is the
algorithm for inserting into BST
(don't care about how it is
implemented for arrays ...)
Once you understand how to insert, look at how you select left/right child of the current node and replace the algorithm with the way you need to access nodes in array based BST, meaning your (left,right) --> [2*i + 1],[2*i + 2] ... This calculation gives you the location of the node in the array
Have a look at the BST description at wikipedia, and the following example:
/* Inserts the node pointed to by newNode into the subtree rooted at treeNode */
void InsertNode(Node* &treeNode, Node *newNode)
{
if (treeNode == NULL)
treeNode = newNode;
else if (newNode->key < treeNode->key)
InsertNode(treeNode->left, newNode);
else
InsertNode(treeNode->right, newNode);
}
Replace the way nodes and values are accessed in array, meaning replace treeNode->key, treeNode->left,treeNode->right with how you would access children nodes and the value in array (calculating the indexes of where in the array you store the values).
You will probably not need to pass Node* around because you'll be operating on an array, and probably you can pass around index to the current node and then just add to it to get the index for left/right children.
Btw (1), if it is array based it is probably not supposed to grow in memory, you create fixed size array at the beginning that is big enough to hold your elements and then you insert your elements into appropriate indexes of that array.
Btw (2), where did you get that comparison tree that you trying to achieve? How can Z be on left path from R? If you insert according to the same algorithm when you insert Z when R is already in tree you do (Z < R ? go left : go right) so Z would end up on right path from the root R (same as when you inserted the first A after R: (A < R ? go left : go right) you ended up inserting A on the left path ...)
Btw (3), it is correct as others mentioned, the final tree depends here on the order of insertion. The most inefficient way of generating tree would be to order elements and insert one by one because you would end up with linked list so traversal would take O(n) instead of O(logN). So if you have fixed set of elements you either pick random or consistently middle element.
I take it, then, that you want to be able to use elements in the array without having to re-arrange the array when you insert a new element?
Clearly, you would want to put the tree's root node at index zero. After that, you could use the path of descent to construct a number in binary. For instance, going down the tree left-left-right-left would give you the number 0b1011 = 11. (I used 1 for left and 0 for right) Add 1 to that, so this node would go at index 12. To descend further in the tree, use a logical or with the direction of descent.
If you want to lay out a complete binary tree in an array, i_left=i_parent*2 and i_right=i_parent*2+1 works well (with i_root=1). BST are supposed to be efficiently updatable by modifying only the nodes along the path from the root to another node in the tree; location-independent explicit left and right subchild pointers (or indices) allow this, because shifting the location (or reuse of) of a subtree doesn't require a deep copy.
The only way it makes sense to have a packed binary search tree (with fixed locations for left and right subtrees based on parent's index, as above) is if the set is fixed; sort it and recurse, grabbing the middle of the sorted subrange and using it as the root of your BST-subtree.