How to read binary tree from file? C++ - c++

How to read file into a binary tree?
I need to read binary tree from a file then mirror it and write it out to another file. I have managed to mirror it, but can't find any way how to read it from file before mirroring. I have seen other people asking it, but none of them seem to get an answer.
#include <iostream>
using namespace std;
// Data structure to store a binary tree node
struct Node
{
int data;
Node *left, *right;
Node(int data)
{
this->data = data;
this->left = this->right = nullptr;
}
};
// Function to perform preorder traversal on a given binary tree
void preorder(Node* root)
{
if (root == nullptr) {
return;
}
cout << root->data << " ";
preorder(root->left);
preorder(root->right);
}
// Function to convert a given binary tree into its mirror
void convertToMirror(Node* root)
{
// base case: if the tree is empty
if (root == nullptr) {
return;
}
// convert left subtree
convertToMirror(root->left);
// convert right subtree
convertToMirror(root->right);
// swap left subtree with right subtree
swap(root->left, root->right);
}
int main()
{
/* Construct the following tree
1
/ \
/ \
2 3
/ \ / \
4 5 6 7
*/
Node* root = new Node(1);
root->left = new Node(2);
root->right = new Node(3);
root->left->left = new Node(4);
root->left->right = new Node(5);
root->right->left = new Node(6);
root->right->right = new Node(7);
convertToMirror(root);
preorder(root);
return 0;
}

With trees, recursive functions are usually the easiest way to go, since they allow you to iterate over the entire tree without having to manually maintain the state of the iteration.
For example, your Node::write() method (that you use to dump the state of your tree to disk) might look something like this (untested pseudocode):
void Node::write(FILE * fpOut) const
{
fprintf(fpOut, "BEGIN Node data=%i\n", data);
if (left) left->write(fpOut);
if (right) right->write(fpOut);
fprintf(fpOut, "END Node\n");
}
For example, for a tree that contains just the root (with data=1) and two children (with data=2 and data=3), that would result in a file that looks like this:
BEGIN NODE data=1
BEGIN NODE data=2
END NODE
BEGIN NODE data=3
END NODE
END NODE
... but how to read it back in? That's a bit trickier, but you can do that with a similar recursive function, something like this (again, untested pseudocode):
Node * readTree(Node * parent, FILE * fpIn)
{
char buf[128];
fgets(buf, sizeof(buf), fpIn);
while(strncmp(buf, "BEGIN NODE data=", 16) == 0)
{
Node * childNode = new Node(atoi(buf+16));
(void) readTree(childNode, fpIn); // recurse to read child node
if (parent)
{
if (parent->left == NULL) parent->left = childNode;
else if (parent->right == NULL) parent->right = childNode;
else
{
printf("File contains more than two children for node!?\n");
delete childNode; // avoid memory leak
break;
}
}
else return node; // return the root of the tree to the caller
}
return NULL;
}

Taking a page from the book of LISP, you could represent your tree as: (whitespace for clarity)
(1
(2
(4 * *)
(5 * *))
(3
(6 * *)
(7 * *)))
with a simple read function as:
Node * readTree(istream& is) {
std::istream::sentry s(is);
if (!s) {
// should not happen!
}
int data;
Node *left=nullptr, *right=nullptr;
if (is.peek() == '(') {
is.get(); // eat (
is >> data;
left = readTree(is);
right = readTree(is);
is.get(); // eat )
return TODO; // create Node from data, left, right
} else if (is.peek() == '*') {
is.get(); // eat *
return nullptr;
} else {
// should not happen!
}
}

Related

Explain left child right sibling traversal

I have a left child right sibling as below:
10
* |
* 2 -> 3 -> 4 -> 5
* | |
* 6 7 -> 8 -> 9 */
I want to traverse from root to the last node, the traversal function is as below:
void traverseTree(Node * root)
{
if (root == NULL)
return;
while (root)
{
cout << " " << root->data;
if (root->child)
traverseTree(root->child);
root = root->next;
}
}
As I understood, if the node has a child, then the pointer points to its child, otherwise points to the sibling (next). In this case, when the pointer points to element 6, it will go to the root->next element (which is NULL). However, the function can still be able to print the remaining element (5,7,8,9). Can any one help me explain how traverseTree works?
Here's the code to recreate the tree:
// CPP program to create a tree with left child
// right sibling representation.
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int data;
struct Node *next;
struct Node *child;
};
// Creating new Node
Node* newNode(int data)
{
Node *newNode = new Node;
newNode->next = newNode->child = NULL;
newNode->data = data;
return newNode;
}
// Adds a sibling to a list with starting with n
Node *addSibling(Node *n, int data)
{
if (n == NULL)
return NULL;
while (n->next)
n = n->next;
return (n->next = newNode(data));
}
// Add child Node to a Node
Node *addChild(Node * n, int data)
{
if (n == NULL)
return NULL;
// Check if child list is not empty.
if (n->child)
return addSibling(n->child, data);
else
return (n->child = newNode(data));
}
// Traverses tree in level order
void traverseTree(Node * root)
{
if (root == NULL)
return;
while (root)
{
cout << " " << root->data;
if (root->child)
traverseTree(root->child);
root = root->next;
}
}
//Driver code
int main()
{
Node *root = newNode(10);
Node *n1 = addChild(root, 2);
Node *n2 = addChild(root, 3);
Node *n3 = addChild(root, 4);
Node *n4 = addChild(n3, 6);
Node *n5 = addChild(root, 5);
Node *n6 = addChild(n5, 7);
Node *n7 = addChild(n5, 8);
Node *n8 = addChild(n5, 9);
traverseTree(root);
return 0;
}
After executing traverseTree(root->child) the control flow will continue from the next line. You're not returning from the function, just calling another function from within this function.
void traverseTree(Node * root)
{
if (root == NULL)
return;
while (root)
{
cout << " " << root->data;
if (root->child)
traverseTree(root->child); // First, if child exists, traverse child. No return statement following here.
root = root->next; // Next, traverse sibling
}
}
If you still have doubts it would do you good to read about the program flow when calling a function.
Update(completely irrelevant to the question): As requested by OP, solution using stack:
void traverseTree(Node * root)
{
if (root == NULL)
return;
stack<Node*> s;
s.push(root);
while (!s.empty())
{
Node* top = s.top();
cout << " " << top->data;
s.pop();
if (top->next) s.push(top->next);
if (top->child) s.push(top->child);
}
}

Accepting tree nodes from keyboard for determining it's height

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);
}

BST node removal function doing sth I don't understand

So I am writing a BST node removal function, but I cannot figure out a problem:
I have this node-data structure:
struct webentry
{
char * topic;
char * keyword;
char * url;
char * summary;
char * review;
int rating;
};
The problem occurs at the point where the node has a two children and its right child has a left child (meaning I need to find the inorder successor and replace it with):
else if ((root->right != NULL) && (root->left !=NULL) && (root->right->left !=NULL))
{
node*tempr = root->right;
node*templ = root->left;
delete root->data.topic;
delete root->data.keyword;
delete root->data.url;
delete root->data.summary;
delete root->data.review;
delete root;
root = findis(tempr);
root->right = tempr;
root->left = templ;
return 1;
}
I wrote a findis function to deal with the inorder successor situation:
node* program4::findis(node* &root)
{
/* cout to figure out what's going on
cout<<"Topic: "<<root->data.topic<<endl; Finds it here
cout<<"Keyword: "<<root->data.keyword<<endl; Finds it here
*/
if ((root->left==NULL) && (root->right ==NULL))
{
node*temp = root;
delete root;
root = NULL;
/*
cout<<"Topic: "<<temp->data.topic<<endl; Empty
cout<<"Keyword: "<<temp->data.keyword<<endl; Finds
*/
return temp;
}
else if ((root->left == NULL) && (root->right != NULL))
{
node*temp= root;
node*tempn = root->right;
delete root;
root = tempn;
/*
cout<<"Topic: "<<root->data.topic<<endl;
cout<<"Keyword: "<<root->data.keyword<<endl;
*/
return temp;
}
else
{
return findis(root->left);
}
The problem is: When the node inorder successor returns, topic part becomes NULL, everything else stays the same. I have used GDB to figure out where it deletes the contents of topic, and it is right where I marked, right after the if condition meets and deletes the root in the findis function. It doesn't delete any other data of the the node, I don't know why it even deletes it. Can anyone see what is happening here?

AVL Tree Traversal from outside Tree class

I am having some trouble with a Tree comparison program I am writing in C++. I am trying to traverse a tree to compare elements in another tree from a comparator class, and I am getting an error that says that I cannot access root in the AVL tree class. The error I am getting is:'class avlTree' has no member named 'root.' Below is my code for the method in question, and after that is the AVL Tree class. I am beginning to wonder if I should pass in the second tree to be compared in the method call to a method within the AVL Tree class, and just traverse the tree, and call to the second tree from within the Tree class. I am very much a beginner at C++, so I apologize in advance for any confusion and/or poor style.
Method
void findCommon(){
if(tree.root == NULL){
return;
}
findCommon(tree.root->left);
if (tree2.find(tree.root) == true){
cout<<tree.root->data<<" ";
}
findCommon(tree.root->right);
}
AVL Tree Class
#include<iostream>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include<string>
#define pow2(n) (1 << (n))
using namespace std;
/*
* Node Declaration
*/
struct avl_node
{
string data;
struct avl_node *left;
struct avl_node *right;
}*root;
/*
* Class Declaration
*/
class avlTree
{
public:
avlTree()
{
root = NULL;
}
/*
* Height of AVL Tree
*/
int height(avl_node *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
/*
* Height Difference
*/
int diff(avl_node *temp)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int b_factor= l_height - r_height;
return b_factor;
}
/*
* Right- Right Rotation
*/
avl_node* rr_rotation(avl_node *parent)
{
avl_node* temp;
temp = parent->right;
parent->right = temp->left;
temp->left = parent;
return temp;
}
/*
* Left- Left Rotation
*/
avl_node* ll_rotation(avl_node *parent)
{
avl_node* temp;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
/*
* Left - Right Rotation
*/
avl_node* lr_rotation(avl_node *parent)
{
return parent;
}
/*
* Right- Left Rotation
*/
avl_node* rl_rotation(avl_node *parent)
{
return parent;
}
/*
* Balancing AVL Tree
*/
avl_node* balance(avl_node *temp)
{
int bal_factor = diff (temp);
if (bal_factor > 1)
{
if (diff (temp->left) > 0)
temp = ll_rotation (temp);
else
temp = lr_rotation (temp);
}
else if (bal_factor < -1)
{
if (diff (temp->right) > 0)
temp = rl_rotation (temp);
else
temp = rr_rotation (temp);
}
return temp;
}
/*
* Insert Element into the tree
*/
avl_node* insert(avl_node *root, string value)
{
if (root == NULL)
{
root = new avl_node;
root->data = value;
root->left = NULL;
root->right = NULL;
return root;
}
else if (value < root->data)
{
root->left = insert(root->left, value);
root = balance (root);
}
else if (value >= root->data)
{
root->right = insert(root->right, value);
root = balance (root);
}
return root;
}
avl_node * minValueNode(avl_node* node)
{
avl_node* current = node;
/* loop down to find the leftmost leaf */
while (current->left != NULL)
current = current->left;
return current;
}
bool find(avl_node* root, string data)
{
// STEP 1: PERFORM STANDARD BST DELETE
if (root == NULL)
return false;
// If the data to be deleted is smaller than the
// root's data, then it lies in left subtree
if ( data < root->data ){
return find(root->left, data);
}
// If the data to be deleted is greater than the
// root's data, then it lies in right subtree
else if( data > root->data ){
return find(root->right, data);
}
else
{
return true;
}
}
// Recursive function to delete a node with given data
// from subtree with given root. It returns root of
// the modified subtree.
avl_node* pick(avl_node* root, string data)
{
// STEP 1: PERFORM STANDARD BST DELETE
if (root == NULL)
return root;
// If the data to be deleted is smaller than the
// root's data, then it lies in left subtree
if ( data < root->data )
root->left = pick(root->left, data);
// If the data to be deleted is greater than the
// root's data, then it lies in right subtree
else if( data > root->data )
root->right = pick(root->right, data);
// if data is same as root's data, then This is
// the node to be deleted
else
{
// node with only one child or no child
if( (root->left == NULL) || (root->right == NULL) )
{
avl_node *temp = root->left ? root->left :
root->right;
// No child case
if (temp == NULL)
{
temp = root;
root = NULL;
}
else // One child case
*root = *temp; // Copy the contents of
// the non-empty child
free(temp);
}
else
{
// node with two children: Get the inorder
// successor (smallest in the right subtree)
avl_node* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->data = temp->data;
// Delete the inorder successor
root->right = pick(root->right, temp->data);
}
}
// If the tree had only one node then return
if (root == NULL)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
//root->height = 1 + max(height(root->left),
// height(root->right));
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to
// check whether this node became unbalanced)
balance(root);
return root;
}
void inOrder(avl_node *root){
if(root == NULL){
return;
}
inOrder(root->left);
cout<<root->data<<" ";
inOrder(root->right);
}
};

List All Function still trying to retrieve a node I deleted from a binary search tree

I have these functions to remove a node from my binary search tree:
bool collection::removeFromTree(const char name[])
{
for (treeNode * curr = root; curr;)
{
int8_t result = strcmp(name, curr->item->getName());
if (result == 0)
{
deleteNode(curr);
return true;
}
else if (result < 0)
curr = curr->left;
else if (result > 0)
curr = curr->right;
}
return false;
}
void collection::deleteNode(treeNode *& goneNode)
{
//if it's a leaf
if (!goneNode->left && !goneNode->right)
{
delete goneNode; //node's destructor gets invoked
goneNode = nullptr;
}
//if it has right child
else if (!goneNode->left)
{
goneNode = goneNode->right;
}
//if it has left child
else if (!goneNode->right)
{
goneNode = goneNode->left;
}
//if it has both children
else
{
treeNode * prev = nullptr;
treeNode * curr = goneNode->right;
while (curr->left)
{
prev = curr;
curr = curr->left;
}
//prev points to the copy over data
delete goneNode->item;
if (!prev)
{
goneNode->item = curr->item;
goneNode->right = curr->right;
curr->item = nullptr;
}
else
{
goneNode->item = curr->item;
curr->item = nullptr;
prev->left = curr->right;
}
}
}
This runs fine, but when I try to list all the elements in my tree after deleting a node (with these functions):
void collection::displayByName() const
{
std::cout << std::endl
<< "========================================" << std::endl;
//display the tree inorder
listAll(root);
}
void collection::listAll(const treeNode * const & root) const
{
if (root)
{
std::cout << *(root->item) << std::endl
<< "========================================" << std::endl;
listAll(root->left);
listAll(root->right);
}
}
I receive this error:
And when I quit the program after deleting a node (invoking these destructors):
collection::~collection()
{
delete root;
}
collection::treeNode::~treeNode()
{
delete left;
delete right;
}
I recieve this error:
Any suggestions would be greatly appreciated because I see no reason for my listAll() function to be calling nodes that I've already deleted.
By the way, this is my struct for my treeNode:
struct treeNode
{
treeNode();
treeNode(vendor *& item);
~treeNode();
vendor * item;
treeNode *left, *right;
};
treeNode * root; //the bst
hashNode ** table; //the hash table
uint8_t capacity;
uint8_t size;
const static uint8_t INIT_CAP = 20;
When you need to remove a node from a singly linked list or a tree, I find using a pointer to pointer is handy. Namely, if we have a treeNode** ptr;, then *ptr is the pointer to our node. So, if ptr = &root, then *ptr = nullptr sets root to nullptr.
I removed the deleteNode function and threw its logic in the removeFromTree function.
bool collection::removeFromTree(const char name[])
{
treeNode** ptr = &root;
Instead of being a pointer to treeNode, ptr will point to a treeNode* inside the tree structure. This way, we can modify the pointer that led us to the current node. The lines marked //same as before have the same logic you were using, just possibly modified to account for the fact ptr has another level of dereferencing to do.
int result; //same as before
while (*ptr) //While we haven't hit a dead end
{
result = strcmp(name, (*ptr)->item->getName()); //same as before
if (result < 0) //same as before
ptr = &((*ptr)->left); //same as before
else if (result > 0) //same as before
ptr = &((*ptr)->right); //same as before
else //begin deleteNode() logic
{
if ((*ptr)->left && (*ptr)->right) //two children
{
Here, we use pointers to member because the alternative was a conditional operator on every line. If a node has two children, we need to find either the rightmost node on the left side, or the leftmost node on the right side. That's the node we can replace the current node with.
treeNode* treeNode::*dir = some_condition ? &treeNode::right : &treeNode::left; //pointer to treeNode member of type treeNode*
treeNode* treeNode::*ndir = some_condition ? &treeNode::left : &treeNode::right; //pointer to treeNode member of type treeNode*
dir now either points to left or right, which is the direction we are searching the tree for. ndir is the opposite direction. So, if we want the rightmost node on the left side, (*ptr)->*dir == (*ptr)->left and (*ptr->*ndir == (*ptr)->right. If we want the leftmost right node, it would be reversed. This is just a more complicated way to do less work, really. It shouldn't be hard to remove. some_condition is just either true or false. true means the left side of the tree (from the current node) loses a node, and false means the right side does.
treeNode** replacement = &((*ptr)->*ndir); //the node to replace the current one with
while ((*replacement)->*dir) //While we aren't at the edge
replacement = &((*replacement)->*dir);
This loops until *replacement is the node we need to replace *ptr with.
treeNode* rep_branch = (*replacement)->*ndir; //If the replacement node had a child, this is now it
(*replacement)->left = (*ptr)->left; //Copy current to replacement
(*replacement)->right = (*ptr)->right; //Copy current to replacement
(*ptr)->left = nullptr; //null out current in case of destructor
(*ptr)->right = nullptr; //null out current in case of destructor
Now, the replacement node is pointing to the node-to-be-deleted's children, and our soon to be expired node has no children anymore. Now, it's safe to delete the unwanted node. If the node class had a destructor to delete its children, the left and right pointers were set to nullptr just in case.
delete *ptr; //delete unwanted node
*ptr = *replacement; //replacement node has taken the unwanted node's place in the tree
*replacement = rep_branch; //The replacement's child takes its own place
}
This completes the tree's structure. Wherever the unwanted node was, the replacement node has taken its place. And because the replacement node was required to be an edge node, it had at most one child. We just replace it with the child.
else if ((*ptr)->left) //one child on left
{
treeNode* current = *ptr;
*ptr = (*ptr)->left; //replace current with left
current->left = nullptr; //null out for safety
delete current;
}
else if ((*ptr)->right) //one child on right
{
treeNode* current = *ptr;
*ptr = (*ptr)->right; //replace current with right
current->right = nullptr; //null out for safety
delete current;
}
else //no children
{
delete *ptr;
*ptr = nullptr;
}
return true; //yay it's over
}
}
return false; //never found it
}
The rest is fairly straightforward, just replacing easier nodes and returning. Hopefully this gives you some ideas about how to approach problems like this, and the occasional uses of some of these structures. This is what I meant about using treeNode** over treeNode* for operations like this.