Copying a binary tree - binary-tree

When asked to create a copy of the binary tree, I have always been told to use a post order traversal logic to make the copy.
Is it not possible to process the original tree in pre-order or in-order to create a copy?
Any traversal method more optimal than the other?
Post-order way:
NODEPTR Copy(NODEPTR p)
{
if (p == null) return p
NODEPTR left = Copy(p-> left)
NODEPTR right = Copy(p-> right)
NODEPTR root = MakeBT(p->data, left, right) //MakeBT is a helper function that makes a tree
return (root)
}
Pre-order way:
NODEPTR Copy(NODEPTR p)
{
if (p == null) return p
NODEPTR root
root->data = p->data
root-> left = Copy(p-> left)
root-> right = Copy(p-> right)
return (root)
}
In-order way:
NODEPTR Copy(NODEPTR p)
{
if (p == null) return p
NODEPTR left = Copy(p-> left)
NODEPTR root
root-> data = p-> data
root-> left = left
root-> right = Copy(p-> right)
return (root)
}

Here is a cpp program to copy a binary tree(Node) to a new binary tree(NewNode).
#include <iostream>
using namespace std;
class Node{
public:
int val;
Node* left=NULL;
Node* right=NULL;
Node(int val){
this->val=val;
this->right=NULL;
this->left=NULL;
}
void insert(int v){
if(this->left==NULL)
this->left=new Node(v);
else if(this->right==NULL)
this->right=new Node(v);
else
cout<<"impossible to insert the node\n";
}
void print(){
cout<<this->val<<" ";
if(this->left) this->left->print();
if(this->right) this->right->print();
}
};
class NewNode{
public:
int val;
NewNode* left=NULL;
NewNode* right=NULL;
NewNode* parent=NULL;
void print(){
cout<<this->val<<" ";
if(this->left) this->left->print();
if(this->right) this->right->print();
}
};
void copy(Node* original,NewNode* duplicate){
duplicate->val=original->val;
// cout<<duplicate->val<<endl;
if(original->left){
NewNode* newLeft=new NewNode;
newLeft->parent=duplicate;
duplicate->left=newLeft;
// printf("in left copying %d %d %d\n",duplicate->val,duplicate->left,duplicate->parent);
copy(original->left,duplicate->left);
}
if(original->right){
NewNode* newRight=new NewNode;
newRight->parent=duplicate;
duplicate->right=newRight;
// printf("in right copying %d %d %d\n",duplicate->val,duplicate->right,duplicate->parent);
copy(original->right,duplicate->right);
}
}
int main(){
Node root(1);
root.insert(2);
root.insert(3);
printf("%d %d %d\n",root.val,root.left,root.right);
Node* temp=root.left;
temp->insert(4);
temp->insert(5);
printf("%d %d %d\n",temp->val,temp->left,temp->right);
NewNode root2;
copy(&root,&root2);
printf("%d %d %d\n",root2.val,root2.left,root2.right);
NewNode *temp1=root2.left;
printf("%d %d %d\n",temp1->val,temp1->left,temp1->right);
root.print();
cout<<endl;
root2.print();
return 0;
}

Related

Why is my create function of binary search tree not working?

The create function is supposed to ask the user how many nodes they want to enter and then insert that many elements one by one.
I am using the pre order traversal function to check the creation of the binary search tree
The code runs fine for the input part, where it is asking the user for data to enter, but when it is supposed to show the tree in pre order traversal manner, it does not do anything and exits.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* left;
struct Node* right;
};
void insert(struct Node* root, int x)
{
if(root -> left == NULL && x < root -> data)
{
struct Node* new_node = (struct Node* )malloc(sizeof(struct Node));
new_node -> data = x;
new_node -> left = NULL;
new_node -> right = NULL;
root -> left = new_node;
}
else if(root -> right == NULL && x > root -> data)
{
struct Node* new_node = (struct Node* )malloc(sizeof(struct Node));
new_node -> data = x;
new_node -> left = NULL;
new_node -> right = NULL;
root -> right = new_node;
}
else
{
if(x < root -> data)
{
insert(root -> left, x);
}
else if(x > root -> data)
{
insert(root -> right, x);
}
}
}
void create(struct Node* root)
{
root = (struct Node*)malloc(sizeof(struct Node));
printf("\nHow many nodes do you want to create: ");
int tree_size;
scanf("%d", &tree_size);
printf("\nEnter data for root node: ");
int ent_data;
scanf("%d", &ent_data);
root -> data = ent_data;
root -> left = NULL;
root -> right = NULL;
for(int i=1; i<tree_size; i++)
{
printf("\nEnter data for node: ");
scanf("%d", &ent_data);
insert(root, ent_data);
}
}
void preOrderTraversal(struct Node *root)
{
if(root != NULL)
{
printf("%d, ", root -> data);
preOrderTraversal(root -> left);
preOrderTraversal(root -> right);
}
}
int main()
{
struct Node* root = NULL;
create(root);
preOrderTraversal(root);
return 0;
}
The problem is that create is not going to modify your main's variable root. C arguments are passed by value, so you should do one of the following:
Pass the address of root to the create function, or
Don't pass root as argument at all, but let create return the root pointer.
The second option is to be preferred, because root does not serve as input value for create, but as output.
Not related to your issue, but try to avoid code repetition. There are three places in your code where you call malloc and initialise a node. instead create a function for that and call it at those three places.
Here is the adapted code:
#include <stdio.h>
#include <stdlib.h>
struct Node
{
int data;
struct Node* left;
struct Node* right;
};
// Function to call whenever you need a node instance
struct Node * create_node(int x)
{
struct Node* new_node = (struct Node*) malloc(sizeof(struct Node));
new_node -> data = x;
new_node -> left = NULL;
new_node -> right = NULL;
return new_node;
}
void insert(struct Node* root, int x)
{
if(root -> left == NULL && x < root -> data)
{
root -> left = create_node(x); // Use function
}
else if(root -> right == NULL && x > root -> data)
{
root -> right = create_node(x); // Use function
}
else
{
if(x < root -> data)
{
insert(root -> left, x);
}
else if(x > root -> data)
{
insert(root -> right, x);
}
}
}
struct Node* create() // No parameter, but return type
{
printf("\nHow many nodes do you want to create: ");
int tree_size;
scanf("%d", &tree_size);
printf("\nEnter data for root node: ");
int ent_data;
scanf("%d", &ent_data);
struct Node* root = create_node(ent_data); // Use function
for(int i=1; i<tree_size; i++)
{
printf("\nEnter data for node: ");
scanf("%d", &ent_data);
insert(root, ent_data);
}
return root; // Return the root
}
void preOrderTraversal(struct Node *root)
{
if(root != NULL)
{
printf("%d, ", root -> data);
preOrderTraversal(root -> left);
preOrderTraversal(root -> right);
}
}
int main()
{
struct Node* root = create(); // No argument, but return value
preOrderTraversal(root);
return 0;
}

Reversing singly linked list using recursion

I have written code to reverse singly linked list using recursion. It is working fine on lists of length less than or equal to 174725. But on lists of length greater than 174725 it gives a segmentation fault(Segmentation fault: 11) while reversing it via reverse() call. Can someone please explain this to me ?
#include <iostream>
using namespace std;
class Node
{
public:
int val;
Node *next;
};
class Sll
{
public:
Node *head;
private:
void reverse(Node *node);
public:
Sll();
void insert_front(int key);
void reverse();
void print();
};
void Sll::reverse(Node *node)
{
if (node == NULL) return;
Node *rest = node->next;
if (rest == NULL)
{
head = node;
return;
}
reverse(rest);
rest->next = node;
node->next = NULL;
return;
}
Sll::Sll()
{
head = NULL;
}
void Sll::insert_front(int key)
{
Node *newnode = new Node;
newnode->val = key;
newnode->next = head;
head = newnode;
return;
}
void Sll::print()
{
Node *temp = head;
while (temp)
{
temp = temp->next;
}
cout << endl;
return;
}
void Sll::reverse()
{
reverse(head);
return;
}
int main()
{
Sll newList = Sll();
int n;
cin >> n;
for (int i = 0; i < n; i++) newList.insert_front(i + 1);
newList.reverse();
// newList.print();
return 0;
}
List reversing function must be tail-recursive, otherwise it is going to overflow the stack when recursing over a long list, like you observe. Also, it needs to be compiled with optimisations enabled or with -foptimize-sibling-calls gcc option.
Tail-recursive version:
Node* reverse(Node* n, Node* prev = nullptr) {
if(!n)
return prev;
Node* next = n->next;
n->next = prev;
return reverse(next, n);
}
An iterative list reversion can be more easily inlined though and it does not require any optimization options:
inline Node* reverse(Node* n) {
Node* prev = nullptr;
while(n) {
Node* next = n->next;
n->next = prev;
prev = n;
n = next;
}
return prev;
}

Binary Search Tree Traversals

I have just started learning Binary Trees and went ahead and tried to implement my own in C. I am kinda lost as to why only InOrder Traversal is displaying correctly while the other two are wrong. I really can't figure this out. I even directly tried inserting nodes, and the result is the same.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
struct Node
{
int val;
struct Node *left;
struct Node *right;
};
//Allocate Memory for New Node
struct Node* getNewNode(int val)
{
struct Node * ptr = (struct Node*)malloc(sizeof(struct Node));
ptr->val = val;
ptr->left = NULL;
ptr->right = NULL;
return ptr;
}
//Insert Node in Binary Search Tree
struct Node* insertNode(struct Node* root,int val)
{
if(root == NULL)
{
root = getNewNode(val);
}
else if(val <= root->val)
{
root->left = insertNode(root->left,val);
}
else
{
root->right = insertNode(root->right,val);
}
return root;
}
void printInorder(struct Node* root)
{
if(root == NULL) return;
printInorder(root->left);
printf("%d ",root->val);
printInorder(root->right);
}
void printPostOrder(struct Node* root)
{
if(root == NULL) return;
printInorder(root->left);
printInorder(root->right);
printf("%d ",root->val);
}
void printPreOrder(struct Node*root)
{
if(root == NULL) return;
printf("%d ",root->val);
printInorder(root->left);
printInorder(root->right);
}
bool search(struct Node* root,int val)
{
if(root == NULL)
{
return false;
}
else if(val == root->val)
{
return true;
}
else if(val < root->val)
{
return search(root->left,val);
}
else
{
return search(root->right,val);
}
}
int main(void)
{
struct Node * root = NULL; //Tree is Empty
root = insertNode(root,15);
root = insertNode(root,10);
root = insertNode(root,8);
root = insertNode(root,12);
root = insertNode(root,20);
root = insertNode(root,17);
root = insertNode(root,25);
printf("Printing In-Order: \n");
printInorder(root);
printf("\nPrinting Post-Order: \n");
printPostOrder(root);
printf("\nPrinting Pre-Order: \n");
printPreOrder(root);
// if(search(root,11))
// {
// printf("\nValue Found\n");
// }
// else
// {
// printf("\nValue Not Found\n");
// }
return 0;
}
Please help me understand if I am doing this wrong or my understanding of traversals is faulty.
The output is as follows:
output terminal
You have copy-paste errors in printPostOrder and printPreOrder - they both call printInorder where they should be calling themselves.

Lowest Common Ancestor of a Binary Search Tree code doesn't pass

can anyone help me with this code? I cannot figure out where I'm blocked.
Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
TreeNode* res=NULL;
int i=0;
postTrav(root,p,q,res,i);
return res;
}
void postTrav(TreeNode* root, TreeNode* p, TreeNode* q,TreeNode* res,int& i){
if(!root){
return;
}
postTrav(root->left,p,q,res,i);
postTrav(root->right,p,q,res,i);
if(root==p||root==q){
i++;
}
if(i==2){
res=root;
i++;
}
}
You may have a logic bug in addition to this, but, because C [I assume] is call-by-value, setting res and i are changed local to a given function invocation, but then discarded. You'll need to pass around some addresses, as below. Especially, note that res is now TreeNode ** in postTrav.
TreeNode *
lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q)
{
TreeNode *res = NULL;
int i = 0;
postTrav(root, p, q, &res, &i);
return res;
}
void
postTrav(TreeNode *root, TreeNode *p, TreeNode *q, TreeNode **res, int *i)
{
if (!root) {
return;
}
postTrav(root->left, p, q, res, i);
postTrav(root->right, p, q, res, i);
if (root == p || root == q) {
*i++;
}
if (*i == 2) {
*res = root;
*i++;
}
}
UPDATE:
The above code is fine. But, whenever, I have a function that needs to return or maintain two or more values [in parallel], a technique I use is to create an additional "traversal" or "helper" struct that simplifies the argument passing.
If you needed an additional variable that needed to be modified/maintained across the calls, instead of adding an additional argument to all functions, it becomes easy/easier to just add another variable to the struct. This works particularly well when you're building up your logic as you go along.
Here's the code for the refinement. Notice that fewer arguments need to be pushed/popped. And, this probably executes as fast or faster than the original. Also, for me, trav->res seems a bit cleaner than *res
// traversal "helper" struct
struct _traverse {
TreeNode *p; // not modified
TreeNode *q; // not modified
TreeNode *res; // result
int i; // depth
// add more variables here as desired ...
#ifdef WANT_TRAVERSAL_STATISTICS
int visited_count; // number of nodes we visited
#endif
};
typedef struct _traverse Traverse;
TreeNode *
lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q)
{
Traverse trav;
trav.p = p;
trav.q = q;
trav.res = NULL;
trav.i = 0;
#ifdef WANT_TRAVERSAL_STATISTICS
trav.visited_count = 0;
#endif
postTrav(root, &trav);
#ifdef WANT_TRAVERSAL_STATISTICS
printf("Visited %d Nodes\n",trav.visited_count);
#endif
return trav.res;
}
void
postTrav(TreeNode *root, Traverse *trav)
{
if (!root) {
return;
}
#ifdef WANT_TRAVERSAL_STATISTICS
trav->visited_count += 1;
#endif
postTrav(root->left, trav);
postTrav(root->right, trav);
if (root == trav->p || root == trav->q) {
trav->i++;
}
if (trav->i == 2) {
trav->res = root;
trav->i++;
}
}
You are not using the property of BST. postTrav should be like this:
TreeNode* postTrav(TreeNode* root, TreeNode* p, TreeNode* q,)
{
if (root == NULL||p==NULL||q==NULL) return NULL;
int n1=p->data;
int n2=q->data;
while (root != NULL)
{
// If both n1 and n2 are smaller than root, then LCA lies in left
if (root->data > n1 && root->data > n2)
root = root->left;
// If both n1 and n2 are greater than root, then LCA lies in right
else if (root->data < n1 && root->data < n2)
root = root->right;
else break;
}
return root;
}

Check if a binary tree is balanced with iterative function?

I need to implement a non-recursive function to determine if a binary tree is balanced or not.
Anyone?
Thanks!!!
Assuming that by "balanced", you mean "height-balanced" in the AVL-tree sense, and you can store arbitrary information for each node,
For each node in post-order,
if either child doesn't exist, assume its respective height is 0.
if the height of both children differs by more than one, the tree is not balanced.
otherwise, this node's height is the larger of both children's heights.
If this point is reached, the tree is balanced.
One way to perform post-order traversal:
start at the root
loop
if this node's left child exists and does not have its height computed, visit its left child next.
else if this node's right child exists and does not have its height computed, visit its right child next.
else
compute this node's height, possibly returning early
if this node is not the root, visit its parent next.
If this point is reached, the tree is balanced.
Try this,
public class BalancedBinaryTree {
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
public boolean isBalanced(TreeNode root) {
if (root==null) {
return true;
}
Stack<TreeNode> stack = new Stack<>();
Map<TreeNode, Integer> map = new HashMap<>();
stack.push(root);
while(!stack.isEmpty()) {
TreeNode node = stack.pop();
if ((node.left==null || (node.left!=null && map.containsKey(node.left))) && (node.right==null || (node.right!=null && map.containsKey(node.right)))) {
int right = (node.right==null) ? 0 : map.get(node.right);
int left = (node.left==null) ? 0 : map.get(node.left);
if (Math.abs(right-left)>1) {
return false;
} else {
map.put(node, Math.max(right, left)+1);
}
} else {
if (node.left!=null && !map.containsKey(node.left)) {
stack.push(node);
stack.push(node.left);
} else {
stack.push(node);
stack.push(node.right);
}
}
}
return true;
}
public static void main(String[] args) {
BalancedBinaryTree b = new BalancedBinaryTree();
boolean v = b.isBalanced(new TreeNode(3, new TreeNode(9), new TreeNode(20, new TreeNode(15), new TreeNode(7))));
System.out.println(v);
v = b.isBalanced(new TreeNode(1, new TreeNode(2, new TreeNode(3, new TreeNode(4), new TreeNode(4)), new TreeNode(3)), new TreeNode(2)));
System.out.println(v);
v = b.isBalanced(new TreeNode(1, new TreeNode(2, new TreeNode(4, new TreeNode(8), null), new TreeNode(5)), new TreeNode(3, new TreeNode(6), null)));
System.out.println(v);
}
}
Here is a c++ code that works, inspired by the postorder traversal. The code is not commented because i do not think a simple comment is enough to explain the whole algorithm. You can execute this code manually with the example below and then you will understand everything.
bool IsBalance(const Node *head)
{
std::stack<const Node *> s;
std::stack<int> sV;
const Node *curr = head, *lastVisit = nullptr;
int deep = 0;
while (curr || !s.empty())
{
while (curr)
{
s.push(curr);
sV.push(-1);
curr = curr->m_pLeft;
}
curr = s.top();
if (sV.top() == -1)
{
sV.top() = deep;
}
if (!curr->m_pRight || curr->m_pRight == lastVisit)
{
if (!curr->m_pRight)
{
deep = 0;
}
if (std::abs(sV.top() - deep) > 1)
{
return false;
}
deep = std::max(sV.top(), deep) + 1;
lastVisit = curr;
s.pop();
sV.pop();
curr = nullptr;
}
else
{
deep = 0;
curr = curr->m_pRight;
}
}
return true;
}
examples:
(1) 21,10,3,1,#,#,5,#,6,#,#,15,12,#,#,18,16,#,#,20,#,#,35,30,22,#,#,#,40,36,#,#,42,#,45,#,#
(2) 1,2,#,4,#,5,#,#,3,6,8,#,#,#,7,#,#
(3) 3,1,#,2,#,#,#
Where nodes are arranged by PreOrder, separated by commas, and # indicates an empty node.
Find the height of left subtree and right subtree for a node of the tree, using Level order traversal and check if that node is balanced.
Repeat this for every node of the tree. For traversing all the nodes we can use level order traversal to avoid recursion.
int height(TreeNode* root){
if(!root){
return 0;
}
queue<TreeNode*> q;
q.push(root);
int count=0;
while(!q.empty()){
int size=q.size();
for(int i=0;i<size;++i){
TreeNode* temp=q.front();
q.pop();
if(temp->left){
q.push(temp->left);
}
if(temp->right){
q.push(temp->right);
}
}
count++;
}
return count;
}
bool checkEveryNode(TreeNode* root){
if(!root){
return true;
}
queue<TreeNode*> q;
q.push(root);
while(!q.empty()){
int count=q.size();
for(int i=0;i<count;++i){
TreeNode* temp=q.front();
q.pop();
int left=height(temp->left);
int right=height(temp->right);
if(abs(left-right)>1){
return false;
}
if(temp->left){
q.push(temp->left);
}
if(temp->right){
q.push(temp->right);
}
}
}
return true;
}
bool isBalanced(TreeNode* root) {
return checkEveryNode(root);
}
Time complexity of this approach is O(n^2), as we need to traverse all the descendant nodes for finding the height of a node(N) and we need to do this for all the nodes(N)

Resources