The following is the code to converted a preorder traversal of a Binary Search Tree to the original tree.
The following code takes an array of integers, which represent the pre order traversal of a a Binary search tree. The root of the construct tree is returned.
struct Node* constructTree(int pre[], int size)
{
stack<struct Node* > s;
int i;
struct Node* root=newNode(pre[0]);
struct Node* temp;
struct Node* top_node;
s.push(root);
for(i=1;i<size;i++)
{
temp=NULL;
while(!s.empty()&&pre[i]>(s.top()->data))
{
temp=s.top();
s.pop();
}
if(temp==NULL)
{
top_node=s.top();
top_node->left=newNode(pre[i]);
s.push(top_node->left);
}else
{
temp->right=newNode(pre[i]);
s.push(temp->right);
}
}
return root;
}
Source: http://www.geeksforgeeks.org/construct-bst-from-given-preorder-traversal-set-2/
I have trouble understanding this code. Can anybody help me understand the following:
At any given iteration, what values are stored in the stack, in relation to the current value being pointed out by pre[i]
Is there any other iterative method for constructing a BST from a given preorder traversal?
Thank you.
After the iteration where the node containing pre[i] is constructed, the stack contains that node on top, under which its leafmost to rootmost ancestors with exactly one child are stored top to bottom.
Check if this works:
public:
TreeNode* bstFromPreorder(vector<int>& preorder) {
TreeNode *root = new TreeNode(preorder[0]);
stack<TreeNode*> nodes;
nodes.push(root);
for (int i = 1; i < preorder.size(); i++) {
TreeNode *temp = new TreeNode(preorder[i]);
if (temp->val < nodes.top()->val)
nodes.top()->left = temp;
else {
TreeNode *prev;
while (!nodes.empty() && nodes.top()->val < temp->val) {
prev = nodes.top();
nodes.pop();
}
prev->right = temp;
}
nodes.push(temp);
}
return root;
}
Related
I'm learning binary trees and want to implement with OOP where I have a struct Node and create a BST Object. I'm trying to create an insert function with this approach and am running into the issue where I can't recursively traverse the tree to add a new node - that is, unless I overload the method, essentially copying it, to call the new method with a pointer to left or right. Hard to explain, but right now I have two methods, and I'm not sure if I'm missing something obvious to just have 1 method with 1 parameter int data, or if this approach just isn't correct. I feel like there's something valuable for me to learn here. Many thanks.
#include <iostream>
struct Node
{
Node *right;
Node *left;
int data;
};
class BST
{
public:
Node* root;
public:
BST()
:root(NULL)
{
}
//inserts node taking parameter data
Node* insertNode(int data)
{
//if tree is empty, create root
if (root == NULL)
{
root = newNode(data);
}
//if data is smaller than or equal to root, insert left
else if (data <= root->data)
{
root->left = insertNode(root->left, data);
}
//data is larger than root, insert right
else
{
root->right = insertNode(root->right, data);
}
return root;
}
//inserts new node
Node* insertNode(Node *root, int data)
{
//if tree is empty, create root
if (root == NULL)
{
root = newNode(data);
}
//if data is smaller than or equal to root, insert left
else if (data <= root->data)
{
root->left = insertNode(root->left, data);
}
//data is larger than root, insert right
else
{
root->right = insertNode(root->right, data);
}
return root;
}
Node* newNode(int data)
{
Node *temp = new Node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return temp;
}
};
int main() {
BST bst1;
bst1.insertNode(30);
bst1.insertNode(15);
return 0;
}
You can save the redundancy by having one call forward to the other:
Node* insertNode(int data)
{
return insertNode(root, data);
}
Note that having identical names for your class member (Node* root) and the local variable in Node* insertNode(Node *root, int data) is error-prone.
Also please do not forget to delete what you new.
This solution shows me segmentation fault, though it works fine for all the trees I tried. can anyone please help me detect the error.
code:
/*Structure of the node of the binary tree is as
struct Node
{
int data;
struct Node* left;
struct Node* right;
};
*/
// function should return the sum of all
// left leaf nodes
int sum=0,i=1;
Node* h;
int leftLeafSum(Node* root)
{
if(i==1)
{
h=root;
i--;
}
Node* temp=root;
if((temp->left!=NULL)&&(temp->left->left==NULL)&& (temp->left->right==NULL))
sum+=temp->left->data;
if(temp->left!=NULL)
leftLeafSum(temp->left);
if(temp->right!=NULL)
leftLeafSum(temp->right);
if(temp==h)
{
i=1;
int s=sum;
sum=0;
return s;
}
}
You need to check that the initial pointer is not equal to NULL:
int leftLeafSum(Node* root)
{
if (root==NULL)
return 0;
...
When I add this in, the website accepts the submission as being correct.
Hi guys I have a doubt in inserting a new node in BST. In the addNode module I am trying to insert an element in the BST, but each time while adding a new node it is adding to the same root node which I passed from main function initially without traversing inside the tree.
This is the code which I have written.
#include<stdio.h>
#include<stdlib.h>
#include<cstdio>
#include<iostream>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
struct node* newNode(int data)
{
node* temp = (node*)malloc(sizeof(struct node));
//struct temp = new node;
temp->data = data;
temp->left = NULL;
temp->right = NULL;
return(temp);
};
int addNode(node *dest, node *root)
{
if(root == NULL)
{
cout<<"adding data to node for "<< dest->data<<endl;
root = dest;
cout<<"ROOT VALUE = root->data "<<root->data<<endl;
return 1;
}
if(dest->data > root->data)
{
cout<<"Traverse right for "<<dest->data<<endl;
addNode(dest, root->right);
}
else if(dest->data < root->data)
{
cout<<"Traverse left for "<<dest->data<<endl;
addNode(dest, root->left);
}
}
void printNodes(node *root)
{
if(root != NULL)
{
printNodes(root->left);
if(root->left != NULL && root->right != NULL)
std::cout<< root->data <<" ";
printNodes(root->right);
}
}
int main()
{
int i, j, k, flag;
int arr[6] = {4, 2,8, 1, 0, 10};
node *start = newNode(arr[0]);
for(i = 1; i < 6; i++)
{
node *newOne = newNode(0);
newOne->data = arr[i];
cout<<"NODE DATA - start->data "<<start->data;
if(addNode(newOne, start))
std::cout<<"\nNode added"<<endl;
}
printNodes(start);
return 1;
}
I am quite new to trees concept as well as pointers concept in trees. Any help is appreciated and thank you.
... but each time while adding a new node it is adding to the same root
node
This is because you are adding it always to the same root, as here
if(addNode(newOne, start))
start is always the same. You could make addNode return the new root and call it like that:
start = addNode(newOne,start);
I'll leave it to you to implement it.
Note that parameters are always passed by value in c++ (unless you pass-by-reference), thus changing the parameter inside the method, root = dest;, has no effect on the start in main.
The code that I tried to print all root to leaf paths in a Binary Tree.
#include<iostream>
#include<stack>
using namespace std;
bool visited[100];
void intilize(){
for(int i=0;i<100;i++)
visited[i]=false;
}
struct node
{
int data;
struct node *left,*right;
};
struct node* createNode(int k)
{
struct node* temp = new node;
temp->left = NULL;
temp->right = NULL;
temp->data = k;
return temp;
}
stack<node*> s,s1;
void print(){
while(!s.empty()){
s1.push(s.top());
s.pop();
}
while(!s1.empty()){
struct node* a= s1.top();
cout<<a->data<<" ";
s1.pop();
s.push(a);
if(s1.empty())
return;
}
}
void printpath(struct node* node){
if(node==NULL) return;
s.push(node);
while(!s.empty()){
struct node* top=s.top();
visited[top->data]=true;
if(top->left!=NULL&&visited[top->left->data]==false)
printpath(top->left);
else if(top->right!=NULL&&visited[top->right->data]==false)
printpath(top->right);
else if(top->left==NULL&&top->right==NULL){
print();
cout<<"\n";
}
s.pop();
}
}
int main() {
struct node* root = createNode(50);
root->left = createNode(7);
root->right = createNode(2);
root->right->left = createNode(1);
root->right->right = createNode(30);
root->right->right->right = createNode(40);
root->right->left->left = createNode(10);
root->right->left->left->left = createNode(12);
intilize();
printpath(root);
return 0;
}
The code gives segmentation fault because there is some issue with the termination condition.
Can someone help me in figuring out the problem.
That approach is over-complicated, and fragile.
A separate stack is not needed for this.
The separate "visible" array is not needed for this.
All that's needed is a stock recursive visitor that recursively descends into this tree, that also takes an additional parameter to a structure that's dynamically built on the stack, which builds the path to the root on the fly, using a link list that goes something like this:
struct path_to_root {
struct path_to_root *next;
struct node *n;
};
Now, all that's needed to print a path to each leaf note is a bog-standard visitor, that recursively iterates over the tree, and this additional parameter. Here's a rough idea of the general approach:
void printpath(struct node *n, struct path_to_root *p)
{
struct path_to_root pnext;
if (!n)
return;
if (!n->left && !n->right)
{
/* Your homework assignment here is to print the path that's in "p" */
}
pnext.n=n;
pnext.next=p;
printpath(n->left, &pnext);
printpath(n->right, &pnext);
}
And this would be invoked as:
printpath(root, NULL);
Your homework assignment, as noted, is to implement the actual code that prints the path to the leaf, using the p parameter, in the space indicated. At that point, the path to the leaf will be found in the p parameter.
Now, one tricky part here is that p will be the leaf's parent, p->next will be its grandparent, and so on. So the path is from the bottom to the top, not top to bottom, but that's a minor detail, that can be handled in the print code.
Or, alternatively, it wouldn't be too much extra work to dynamically build the path to the leaf from top to bottom, in the same manner.
I have a preorder traversal of a binary tree that is stored in an array and I would like to recreate the binary tree based on this traversal. My array looks like this: {NNNLLNLLNLNLNNLLNLL}, where N represents a node and L represents a leaf. I would like to do this recursively but I am having trouble coming up with an algorithm. Any suggestions would be very appreciated.
This should work assuming every node has 2 or 0 descendants (a tree that satisfies this property is called full or strict binary tree)
void create_from_traversal(Node* root, int& index) {
if (traversal[index] == 'L') {
root->left = root->right = NULL;
return;
}
root->left = new Node();
create_from_traversal(root->left, ++index);
root->right = new Node();
create_from_traversal(root->right, ++index);
}
Complete example with check:
#include <string>
#include <iostream>
class Node {
public:
Node* left;
Node* right;
};
std::string traversal = "NNNLLNLLNLNLNNLLNLL";
void create_from_traversal(Node* root, int& index) {
if (traversal[index] == 'L') {
root->left = root->right = NULL;
return;
}
root->left = new Node();
create_from_traversal(root->left, ++index);
root->right = new Node();
create_from_traversal(root->right, ++index);
}
void print_traversal(Node* root) {
if (root->left == NULL) {
std::cout << "L";
return;
}
std::cout << "N";
print_traversal(root->left);
print_traversal(root->right);
}
int main() {
Node* root = new Node();
int index = 0;
create_from_traversal(root, index);
// Does it work?
print_traversal(root); // Output should be equal to given traversal
std::cout << std::endl;
}
Output:
NNNLLNLLNLNLNNLLNLL
You need one more traversal before you can reconstruct the tree. Given any two traversals among the three (Pre, Post, In) you can reconstruct. But given only one it is not possible to uniquely reconstruct the tree.