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.
Related
I have a code that can determine tree height by hard coding it's values
I tried using container like structures but still was not successful, instead of posting what I have tried on the part of accepting tree nodes fro the Input which is actually messy,I decided to post the code with hard coded tree nodes, what I need is for the program to accept tree nodes from the keyboard with the following helper description for input
Input:
The first line is an integer N indicating the number of nodes.
For each of the next few lines, there are two integers include a and b.b is a child of a.
example:
5 // number of nodes
1 2
1 3
3 4
3 5
in which the height will be 3
// C++ program to find height of tree
#include <bits/stdc++.h>
using namespace std;
/* A binary tree node has data, pointer to left child
and a pointer to right child */
class node
{
public:
int data;
node* left;
node* right;
};
/* Compute the "maxDepth" of a tree -- the number of
nodes along the longest path from the root node
down to the farthest leaf node.*/
int maxDepth(node* node)
{
if (node == NULL)
return 0;
else
{
/* compute the depth of each subtree */
int lDepth = maxDepth(node->left);
int rDepth = maxDepth(node->right);
/* use the larger one */
if (lDepth > rDepth)
return(lDepth + 1);
else return(rDepth + 1);
}
}
/* Helper function that allocates a new node with the
given data and NULL left and right pointers. */
node* newNode(int data)
{
node* Node = new node();
Node->data = data;
Node->left = NULL;
Node->right = NULL;
return(Node);
}
// Driver code
int main()
{
node *root = newNode(1);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(4);
root->left->right = newNode(5);
cout << "Height of tree is " << maxDepth(root);
return 0;
}
Since the input identifies the parent node by its data value, we need a helper function to find it:
node *findNode(node *node, int data)
{
if (!node) return 0;
if (node->data == data) return node;
class node *found;
(found = findNode(node->left, data)) || (found = findNode(node->right, data));
return found;
}
Then we can code the input processing, e. g.:
node *node, *root = 0; // initially empty
int nn, a, b;
cin>>nn;
while (cin>>a>>b)
{
if (!root)
root = newNode(a),
node = root;
else
node = findNode(root, a);
if (!node->left) node->left = newNode(b);
else node->right = newNode(b);
}
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.
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.
I'm attempting to build a binary search tree and then do a horizontal inorder print with the left most node as the first node displayed. Also, preceding each node is its depth (distance from root) as well as a tilde to help visualize the tree itself. Conceptually my code seems to be correct, but for whatever reason I can't seem to get it to build the tree properly. I figure that the error is most likely in my insert function, but I can't seem to locate it.
Any suggestions or ideas would be extremely helpful!
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <algorithm>
using namespace std;
typedef struct treeNode {
treeNode *leftChild;
treeNode *rightChild;
int data;
} treeNode;
void printTree(treeNode*);
int getNodeDepth(treeNode*);
treeNode* insert(treeNode*, int);
treeNode* createNewNode(int);
int main()
{
//read in file here
treeNode *root = NULL;
root = insert(root, 8);
root = insert(root, 1);
root = insert(root, 90);
root = insert(root, 3);
root = insert(root, 80);
root = insert(root, 6);
root = insert(root, 83);
printTree(root);
return 0;
}
/*
Purpose: Constructs a new node for the tree.
Inputs: The data for the node.
Outputs: returns the new node
*/
treeNode* createNewNode(int data)
{
treeNode *newNode = new treeNode;
newNode->data = data;
newNode->leftChild = NULL;
newNode->rightChild = NULL;
return newNode;
}
/*
Purpose: Calculates the depth of a given node using recursion.
Inputs: The node to check the depth on.
Outputs: returns the depth
*/
int getNodeDepth(treeNode *node)
{
if (node == NULL) // tree doesn't exist
return(0);
return(1 + max(getNodeDepth(node->leftChild), getNodeDepth(node->rightChild)));
}
/*
Purpose: Inserts a node into the tree.
Inputs: The node to be inserted and the data for the node.
Outputs: returns the inserted node
*/
treeNode* insert(treeNode *node, int data)
{
if (node == NULL)
return createNewNode(data);
else
{
if (data <= node->data)
{
node->leftChild = insert(node->leftChild, data);
}
else
{
node->rightChild = insert(node->rightChild, data);
}
return node;
}
}
/*
Purpose: Prints the BST in a horizontal inorder format.
Inputs: The root node.
Outputs: nothing
*/
void printTree(treeNode *node)
{
if (node == NULL)
return;
printTree(node->leftChild);
cout << "(" << (getNodeDepth(node)-1) << ") ";
for (int i=0; i<(getNodeDepth(node)-1); i++)
cout << "~";
cout << node->data << endl;
printTree(node->rightChild);
}
The current output is as follows:
(2) ~~1
(1) ~3
(0) 6
(3) ~~~8
(1) ~80
(0) 83
(2) ~~90
Obviously it can't have two roots (ie 6 and 83). Thanks!
For those in the future who wish for a correct implementation of the answer to my original question here is the refactored code that I came up. I decided to take an OOP approach and modified the insert and getNodeDepth function to appropriately work.
//
// Binary Search Tree
//
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <iomanip>
#include <algorithm>
using namespace std;
// binary search tree
class BST {
private:
typedef struct treeNode {
treeNode *leftChild;
treeNode *rightChild;
int data;
} treeNode;
treeNode *root;
public:
//Constructor
BST() { root = NULL; }
/*
Purpose: Constructs a new node for the tree.
Inputs: The data for the node.
Outputs: returns the new node
*/
treeNode* createNewNode(int data)
{
treeNode *newNode = new treeNode;
newNode->data = data;
newNode->leftChild = NULL;
newNode->rightChild = NULL;
return newNode;
}
//Check if the tree is empty
bool isEmpty() const { return root==NULL; }
/*
Purpose: Calculates the depth of a given node using recursion.
Inputs: The node to check the depth on and the node to check the depth from.
Outputs: returns the depth
*/
int getNodeDepth(treeNode *node, treeNode *from)
{
if (node == from)
return 0;
else if (node->data < from->data)
return getNodeDepth(node, from->leftChild) + 1;
else
return getNodeDepth(node, from->rightChild) + 1;
}
/*
Purpose: Inserts a node into the tree.
Inputs: The data for the node.
Outputs: none
*/
void insert(int newData)
{
treeNode* t = createNewNode(newData);
treeNode* parent;
parent = NULL;
if(isEmpty()) //check if tree exists or not
root = t;
else {
//Note: ALL insertions are as leaf nodes
treeNode* curr;
curr = root;
// Find the Node's parent
while(curr)
{
parent = curr;
if (t->data > curr->data)
curr = curr->rightChild;
else
curr = curr->leftChild;
}
if ((t->data) < (parent->data))
parent->leftChild = t;
else
parent->rightChild = t;
}
}
/*
Purpose: Prints the BST in a horizontal inorder format.
Inputs: The root node.
Outputs: nothing
*/
void printTree(treeNode *node)
{
if (node == NULL)
return;
printTree(node->leftChild);
cout << "(" << getNodeDepth(node, root) << ") ";
for (int i=0; i<getNodeDepth(node, root); i++)
cout << "~";
cout << node->data << endl;
printTree(node->rightChild);
}
//Getter for private member variable root
void printInorder()
{
printTree(root);
}
};
int main()
{
// read file in here
BST temp;
temp.insert(8);
temp.insert(1);
temp.insert(90);
temp.insert(3);
temp.insert(80);
temp.insert(6);
temp.insert(83);
temp.printInorder();
return 0;
}
The correct output looks as follows with 8 as the root:
(1) ~1
(2) ~~3
(3) ~~~6
(0) 8
(2) ~~80
(3) ~~~83
(1) ~90
Hope this helps!
In the first you shouldn't write treeNode twice
typedef struct {
treeNode *leftChild;
treeNode *rightChild;
int data;
} treeNode;
In the second you create a memory leak:
treeNode *root = new treeNode;
root = NULL;
You should write:
treeNode *root = NULL;
Obviously it can't have two roots (ie 6 and 83). Thanks!
6 and 83 aren't roots. 8 is a root. So your program gave right answer.
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;
}