Recursive tree symmetry - c++

I have written the following code snippet to determine if a Binary Tree is symmetrical or not:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
bool symmetricityChecker(TreeNode* root, int level) {
bool isValid=false;
if(root==NULL)
return true;
if(level==1)
isValid = root->left->val==root->right->val;
if(root->left!=NULL && root->right!=NULL) {
if(root->left->left!=NULL && root->right->right!=NULL)
isValid = root->left->left->val==root->right->right->val;
if(root->left->right!=NULL && root->right->left!=NULL)
isValid = root->left->right->val==root->right->left->val;
}
return isValid && symmetricityChecker(root->left, level+1) && symmetricityChecker(root->right, level+1);
}
bool isSymmetric(TreeNode* root) {
return symmetricityChecker(root, 0);
}
};
My aim is, at level 1, I check if the root's left and right children are equal (since at this level there is just a root and its two children). For all the remaining levels, I check if the left child of the root's left child is equal to the right child of the root's right child. Similarly, I check if the right child of the root's left child is equal to the left child of the root's right child. (This is so, because the symmetry of the root's immediate left and right children has already been checked in the previous recursive call).
I believe that my algorithm is correct, but it is generating incorrect results. Could someone kindly point out if my logic is incorrect, or are there errors in the implementation?
Edit: I tested the code for the input [1,2,2,3,4,4,3]. I expect the answer to be true, but get a false instead. Hence I am not sure if I have a logical flaw in my approach.

The wrong part is where you're doing that:
return isValid && symmetricityChecker(root->left, level+1) && symmetricityChecker(root->right, level+1);
By calling symmetricityChecker on a single child node, you're expecting the children to be symmetric as well, but this shouldn't be true. So it'll fail because the subtree [2,3,4] is not symmetric and consider the whole tree as not symmetric even if this is not true.
To check symmetry recursively, you have to keep two nodes (i.e. left and right) as your state, not just one. Once you confirm that the two nodes are symmetric, recursively check their children by a similar check to what you're doing above in the nested if conditions.
Another approach is to write a BFS, and check that all the nodes in the same level are symmetric. This way, it should be as easy as checking if an array is symmetric because you'll have all the nodes of the same level in the same array next to each other.
EDIT:
Adding a pseudocode:
bool symmetricityChecker(left, right) {
// Write the base case, check for nulls, corner cases, etc.
if(left != right) return false
return symmetricityChecker(left.left, right.right) &&
symmetricityChecker(left.right, right.left)
}
At the beginning when you only have the root, call this method with the root's children.

Related

Expression Tree implementation issues

I'm having a headache trying to build an expression tree, in particular the pointers for the treenodes, which i have no clue on how to implement and actually create the nodes to store data which is supposed to be pretty basic but the code just confuses me.
For example, when i want to create an expression of 5 + 5 this is what it should look like:
+
/ \
5 5
However when implementing this, i'm not sure how to begin. How do i get the operator in the root node and the numbers as children? I know i can store them in a stack and read off the top however the set parent, left child and right child methods only take (TreeNode *) arguments while the vector tokens are type string.
Also the constructor for the TreeNode take an integer and operator value, why is that? How can i get those values into their respective nodes as root, parent and children?
ExprTree.cpp
#include "ExprTree.h"
#include <sstream>
#include <iostream>
TreeNode * createOperatorNode(const string & op){
if (op == "+") return new TreeNode(Plus);
if (op == "-") return new TreeNode(Minus);
if (op == "*") return new TreeNode(Times);
if (op == "/") return new TreeNode(Divide);
return new TreeNode(NoOp);
}
/*
* Basic constructor that sets up an empty Expr Tree.
*/
ExprTree::ExprTree(){
this->root = NULL;
this-> _size = 0;
}
/*
* Constructor that takes a TreeNode and sets up an ExprTree with that node at the root.
*/
ExprTree::ExprTree(TreeNode * r){
this->root = r;
}
ExprTree ExprTree::buildTree(vector<string> tokens){
// the tokens are the broken up arithimec expression
i.e
5
+
5
// not sure what to do here, i've tried using stacks but i wasn't sure how to get the stored data into the nodes.
}
TreeNode.cpp
#include "TreeNode.h"
TreeNode::TreeNode(Operator o){
op = o;
parent = 0;
leftChild = 0;
rightChild = 0;
}
TreeNode::TreeNode(int val){
op = Value;
value = val;
parent = 0;
leftChild = 0;
rightChild = 0;
}
TreeNode.h
#include <string>
#include <sstream>
enum Operator {Value, Plus, Minus, Times, Divide, NoOp};
class TreeNode {
private:
Operator op; //If this node represents an operator, this is where it's stored.
//It can take values from the Operator enum (i.e. Plus, Minus, etc.)
//If it represents a value, use the Value value. :D
int value; //If this node stores an actual number, this is it.
TreeNode * parent; //Pointer to the parent.
TreeNode * leftChild; //Pointer to the left child of this node.
TreeNode * rightChild; //Pointer to the right child of this node.
public:
TreeNode(Operator); //Constructor to use for +, -, * and /.
//Example: TreeNode(Plus);
TreeNode(int); //Constructor to use for actual numbers.
//Example: TreeNode(5);
void setParent(TreeNode *); //Set the parent pointer.
void setLeftChild(TreeNode *); //Set the left child pointer.
void setRightChild(TreeNode *); //Set the right child pointer.
TreeNode * getParent(); //Get the parent pointer.
TreeNode * getLeftChild(); //Get the left child pointer.
TreeNode * getRightChild(); //Get the right child pointer.
int getValue(); //Returns the stored value;
Operator getOperator(); //Returns the stored operator.
bool isValue(); //Returns true if this node is a Value node.
bool isOperator(); //Returns truee if this node is Plus, Minus, Times or Divide node.
std::string toString(); //Returns a simple string representation of the node.
};
The easiest way of parsing expressions is to build a recursive descent parser. This consists of mutually recursive functions called expression, term, and factor. A factor is the smallest unit, either a basic number or open parentheses, expression, close parentheses (so the mutual recursion comes in). Terms are collections of factors with multiplication and divide operators, and expressions are collections of terms joined by plus and minus operators.
You need a special rule for unary minus.
Now a recursive descent parser doesn't actually build a tree as a structure in memory. The tree is implicit in the call pattern. However if you want a tree you can easily enough modify it to build one.
It might help to take a look at my very simple Basic interpreter
https://github.com/MalcolmMcLean/minibasic
You simply use what TreeNode.h gives you.
For instance, if you want to create a tree with the name root that represents 5 + 5, you go like
TreeNode root(Plus);
root.setLeftChild(new TreeNode(5));
root.setRightChild(new TreeNode(5));
Within a parser, well, try to build one. Note that you can traverse your tree easily by following children and parent pointers.
Another way would be to create a constructor over a string, which evaluates as the outermost operator and then recursively constructs it's children by giving them the appropriate substrings, like
TreeNode::TreeNode(string expression){
if(expression is number){
create this as number node
}
create this as operator node with outermost operator
split string by outermost operator
set left child to left side of split string
set right child to ...
}
That said, as a remark, I don't see ~TreeNode() being defined, which means that you will have a memory leak.
Also, I recommend to separate Tree and TreeNode, that is to create a class Tree which has TreeNode as an inner class, and that the constructor and destructor of TreeNode is private (with Tree as a friend). Gives you more control over things. Actions such as setLeftChild can be dangerous in regard to memory leaks if done incorrectly and one would be able to create loops (which defies the idea of a tree).
First, convert your expression into a postfix expression (Infix To Postfix).
Expression : 5 + 5
Postfix : 5 5 +
Then parse the postfix string and whenever you find an operand push it into a stack, or if you find an operator then pop the two operands from the stack (if it's a binary operator) and then assign the tree root as the operator the left & right child as the operands.
Tree *t;
Stack<string> stack;
// parsing the tokens(expression)...
for(int i=0; i<token[i].length(); i++) {
if(token[i] == "+" || token[i] == "-" || token[i] == "*" || token[i] == "/") {
string op1 = stack.top(); stack.pop();
string op2 = stack.top(); stack.pop();
t->root = new createOperatorNode(token[i]);
t->leftChild = new TreeNode(op1);
t->rightChild = new TreeNode(op2);
}
else {
stack.push(token[i]);
}
}

Creating a function that returns a new identical binary tree and adds new nodes to all pre-existing leaves

Create a function that returns a new binary tree identical to the binary tree passed in except that every leaf in the new tree now has a left child and a right child whose values are equal to x and y.
You were close. The case that handles the expansion is correct, but you messed up the iteration a bit. Here's a possible solution:
void expand_leaf(TreeNode * node, int x, int y)
{
// recursively iterate over tree:
if (node->left) expand_leaf(node->left, x, y);
if (node->right) expand_leaf(node->right, x, y);
// expand leafes:
if (!node->left && !node->right)
{
node->left = new TreeNode(x, nullptr, nullptr);
node->right = new TreeNode(y, nullptr, nullptr);
}
}
Your problem can be elegantly decomposed into two sub-problems:
Find all leafs in the tree.
Add children x and y to leafs.
One viable way to find all leafs, is to iterate over ALL nodes of the tree and check if they are leafs (if their left/right pointers are null). This is what the first part of the above expand_leaf function does: Whenever a child pointer is present, it is recursively visited. This effectively visits all nodes of the entire tree.
Now that we have a means to visit all nodes, we can filter out the leafs. This is what the second part of the function does. Whenever we discover a leaf, we add the x/y children to it.
It is very important that the expansion happens after the recursive call. Otherwise we would end up in an infinite loop. Consider why.
Comments on original solution
The abort condition/base case is needed and mostly correct, but you create a new TreeNode prematurely. If you then discover that node==null, you overwrite the just-created n with null also, which results in a memory leak. Solution: Simplify the base case to if (node == nullptr) return nullptr; and move TreeNode * n = new TreeNode; past the if, once you know that you aren't dealing with a null node.
The rest looks functionally correct (haven't run the code). Perhaps it can be improved further for readability?
I would do it as follows:
# define KEY(p) (p->data)
# define LLINK(p) (p->left)
# define RLINK(p) (p->right)
TreeNode * expand_leaf(TreeNode * node, int x, int y)
{
if (node == nullptr)
return nullptr; // copy of empty tree is an empty tree
TreeNode * root = new TreeNode(KEY(node)); // node copy with its key
if (LLINK(node) == nullptr and RLINK(node)) // node is leaf? (this is the base case)
{ // yes ==> create children with x and y
LLINK(root) = new TreeNode(x);
RLINK(root) = new TreeNode(y);
return root;
}
LLINK(root) = expand_leaf(LLINK(node), x, y);
RLINK(root) = expand_leaf(RLINK(node), x, y);
return root;
}
For simplicity, I assume a constructor for TreeNode class which receives the key. If you have not it, then you could add an additional line for setting the key value

function to rebalance binary search tree

I am working on implementing a binary search tree. One of the functions required to complete the implementation is a rebalance function.
According to the specifications the function works in the following way:
The rebalance() method should create a balanced tree and thereby reduce skewness to zero. A
balanced tree is one in which the size of the left and right subtrees differ by no more than 1,
throughout the tree (i.e., every subtree is also balanced).
To balance the tree, the rebalance() method should repeatedly move the root value to the smaller
subtree, and move the min/max value from the larger subtree to the root, until the tree is balanced.
It should then recursively balance both subtrees.
So far I have the following code:
struct treeNode {
Type value;
int count;
treeNode* left;
treeNode* right;
};
treeNode* root;
template <class Type>
void bstree<Type>::rebalance(treeNode* sroot){
if (root == NULL) {
throw new underflow_error("tree is empty");
}
while (skewness(sroot) != 0)
{
if (size(sroot->left) < size(sroot->right))
{
sroot->left.insert(sroot->value);
sroot->left.insert(max(sroot->right));
sroot->left.insert(min(sroot->right));
}
else
{
sroot->right.insert(sroot->value);
sroot->left.insert(max(sroot->left));
sroot->left.insert(min(sroot->left));
}
}
rebalance(sroot->left);
rebalance(sroot->right);
}
I can't tell if I have followed the specifications correctly or not. Can I get some insight or pointers as where I may have done things wrong?
You have not followed the specifications correctly. For one thing, your rebalance operation increases the size of the tree. For another, the result is not always a binary search tree.
You must understand how these trees work before you attempt to implement them. There is just no way around that. I advise you to study your text (or wikipedia) and try constructing and balancing some trees with pencil and paper.

How to iterate in order for a custom map?

I am looking to build my own map class. (Which will behave exactly like the C++ STL) I want to be able to iterate through all the elements in order by key value.
I implemented my map as an unbalanced binary search tree.
So my question is how to do an iterator increment efficiently. One inefficient way is to iterate through every single element in the tree to find the next lowest key. Is there a faster way to do this?
Thank you.
It depends a bit on the implementation details. If the nodes of your unbalanced binary search tree have a "parent" pointer, you could use that to traverse it. Your implementation of ++iterator could look a bit like this:
if (current_node.has_right_child()) {
// We go to the right subtree of the current node and
// take the smallest element of that subtree.
current_node = current_node.right_child();
while (current_node.has_left_child()) {
current_node = current_node.left_child();
}
} else {
// We have to go up. If the current element is the left child of the parent,
// we can just go to the right child of the parent.
// If it is the right child, we have to go further up
while (true) {
if (!current_node.has_parent()) {
// We got up to the root and never found a right child.
// So we are at the end of the iteration.
current_node = NULL;
break;
}
Node* parent = current_node.parent();
bool is_left_child = parent.left_child() == current_node;
current_node = parent;
if (is_left_child) {
// if this was the left child, then the parent is the correct next element.
break;
}
// if this was the right child, we have to go further up
// until we leave this subtree, so we continue iterating.
}
}
If your binary tree does NOT have parent nodes, you could store the parents in the iterator. I.e. you could maintain a vector parents; in which you store the parents of the current node up to the root. If this is still needed, I can provide an implementation, but because you edited my "non parent pointer" version with parent pointers, it seems that you have parent pointers. So I leave it away.

How does the std::map iterator work?

The C++ STL class std::map implements O(log(n)) look-up using a binary tree. But with trees, it's not immediately obvious how an iterator would work. What does the ++ operator actually mean in a tree structure? Whereas the concept of "next element" has an obvious implementation in an array, for me it's not so obvious in a tree. How would one implement a tree iterator?
For an inorder traversal (probably works for others too), if you have a parent-pointer in your nodes you can do a non-recursive traversal. It should be possible to just store two pointers in your iterator: you need an indication of where you are, and you'll probably (I'm not doing the research now) need something like a "previous" pointer so you can figure out your current movement direction (i.e. do I need to go into the left subtree, or did I just come back from it).
"Previous" will probably be something like "parent", if we've just entered the node; "left" if we're coming back from the left subtree, "right" if we are coming back from the right subtree, and "self" if the last node we returned was our own.
I would like to add my two cents worth as a comment, but since I am not able to I shall have to add an answer.  I have been googling and was frustrated because all the answers I found, these excepted, assumed a stack or some other variably-sized data structure. I did find some code.  It shows that it can be done without a stack but I found it hard to follow and so decided to attack the problem from first principles.
The first thing to note is that the algorithm is "left-greedy".  Thus, when we start at the root we immediately go as far left as possible, since the leftmost node is the one we need first.  This means that we never need to consider the left-subtree.  It has already been iterated over.
The order of iteration is left subtree, node, right subtree.  So if we are positioned at a given node we know that its left subtree and the node itself have been visited and that we should next visit the right subtree, if any, going as far left as possible.
Otherwise, we must go up the tree.  if we are going from a left child to its parent then the parent comes next.  (Afterwards we will visit its right subtree, as already covered.)
The final case is when we are going from a right child to its parent.  The parent has been visited already so we must go up again.  In fact we must keep going up until we reach the root or the tree, or find ourselves moving to a parent from its left child. As we have already seen, the parent is the next node in this case.  (The root may be indicated by a null pointer, as in my code, or some special sentinel node.)
The following code could easily be adapted for an STL-style iterator
// Go as far left from this node as you can.
// i.e. find the minimum node in this subtree
Node* Leftmost(Node* node)
{
if (node == nullptr)
return nullptr;
while (node->left != nullptr)
node = node->left;
return node;
}
// Start iterating from a root node
Node* First(Node* root)
{
return Leftmost(root);
}
// The iteration is current at node. Return the next node
// in value order.
Node* Next(Node* node)
{
// Make sure that the caller hasn't failed to stop.
assert(node != nullptr);
// If we have a right subtree we must iterate over it,
// starting at its leftmost (minimal) node.
if (node->right != nullptr)
return Leftmost(node->right);
// Otherwise we must go up the tree
Node* parent = node->parent;
if (parent == nullptr)
return nullptr;
// A node comes immediately after its left subtree
if (node == parent->left)
return parent;
// This must be the right subtree!
assert(node == parent->right);
// In which case we need to go up again, looking for a node that is
// its parent's left child.
while (parent != nullptr && node != parent->left)
{
node = parent;
parent = node->parent;
}
// We should be at a left child!
assert(parent == nullptr || node == parent->left);
// And, as we know, a node comes immediately after its left subtree
return parent;
}
Consider the set of all elements in the map that are not less than the current element that are also not the current element. The "next element" is the element from that set of elements that is less than all other elements in that set.
In order to use a map, you must have a key. And that key must implement a "less than" operation. This determines the way the map is formed, such that the find, add, remove, increment, and decrement operations are efficient.
Generally the map internally uses a tree of some kind.
Standard implementation of map iterator operator++ watch in stl_tree.h:
_Self&
operator++() _GLIBCXX_NOEXCEPT
{
_M_node = _Rb_tree_increment(_M_node);
return *this;
}
_Rb_tree_increment implementation is discussed here