Similar Binary Trees - c++

I have written the following function to check of two b-trees are similar or not. But I am not getting the desired output.
int bt_similar(btree *b1, btree *b2)
{
int m=1;
if ((b1->data==b2->data&&(((b1->lchild==NULL&&b2->lchild==NULL)||(b1->lchild!=NULL&&b2->lchild!=NULL))&&((b1->rchild==NULL&&b2->rchild==NULL)||(b1->rchild!=NULL&&b2->rchild!=NULL))))&&(m))
{
if (b1->lchild!=NULL)
m=bt_similar(b1->lchild,b2->lchild);
if (b1->rchild!=NULL)
m=bt_similar(b1->rchild,b2->rchild);
if (m)
return 1;
}
return 0;
}

Firstly, you could benefit a lot from breaking up your code, in particular that big condition in the if statement on the fourth line is nasty. Why not just handle the null case in the method itself? eg:
if (b1 == null && b2 != null)
return 0;
if (b2 == null && b1 != null)
return 0;
if (b1 == null && b2 == null)
return 1;
As far as I can tell, the actual problem with your code is where you overwrite the value of m at line 9, without taking the previous value into consideration. If the left-hand-side of the tree is not similar but the right is, the return will be 1. Instead of:
if (b1->lchild!=NULL)
m=bt_similar(b1->lchild,b2->lchild);
if (b1->rchild!=NULL)
m=bt_similar(b1->rchild,b2->rchild);
You should have:
if (b1->lchild!=NULL)
m = bt_similar(b1->lchild,b2->lchild);
if (b1->rchild!=NULL)
m = m && bt_similar(b1->rchild,b2->rchild);

you should make sure that if b1 == NULL or b2 == NULL...
bool compare(struct node* b1, struct node* b2) {
// 1. both empty -> true
if (b1==NULL && b2==NULL) return(true);
// 2. both non-empty -> compare them
else if (b1!=NULL && b2!=NULL) {
return(
b1->data == b2->data &&
compare(b1->lchild, b2->lchild) &&
compare(b1->rchild, b2->rchild));
}
// 3. one empty, one not -> false
else return false;
}
and, b-tree is not short for binary tree.

Related

Recursive functions with || operator?

So I was tinkering with || and && operators with return. I developed an understanding by comparing int as for example return 1 || 0; return 0 || 0; that the program returns 1 or 0 in case of an int function and true or false in case of bool functions after comparing values.
Now I was writing a code to find path sum to given value using implementation of trees.
bool HasPathSum(ds::sn::BNode<int>* root, int value)
{
if (!root && !value)
{
return true;
}
else if(root)
{
return HasPathSum(root->left, value - root->data)
|| HasPathSum(root->right, value - root->data);
}
return false;
}
I managed to write it after massive tinkering. For recursion I was doing
HasPathSum(root->left, value - root->data);
return HasPathSum(root->right, value - root->data);
To explore all the paths, but it wasn't quite all right because if the path sum was in left, It did go to true but eventually returned false. I figured I will have to write the recursive definition in a single line for it to work and wrote || just as an experiment and it blew my mind that it actually worked. I wrote std::cout << value << " "; at the top of if statement to see what is happening and it does what its supposed do and stops just as a path has been found.
This is all that I've tried but I am unable too wrap my head around how the recursive function with || works or will work if given &&.
If someone experienced can provide an explanation! :)
operator || and operator && does short circuit, so might doesn't evaluate second operand depending of the first one.
bool b = f() || g(); is mostly equivalent to
bool b = f();
if (b == false) b = g();
bool b = f() && g(); is mostly equivalent to
bool b = f();
if (b == true) b = g();

storing the number of certain leaves in the nodes of the binary search tree(optimization)

I have to count for each subtree the number of leaves with even label whose father has odd label and the number of leaves with odd label whose father has even label and store that number in the subtree's node.
For example : this tree (the output is on the left).
This is my code
struct node {
int label;
node*right;
node*left;
int L; //i use this to store the number of leaves
};
void addnodeBST(node*&tree, int l) { //adds a node
if (!tree) {
tree = new node;
tree->label = l;
tree->right = tree->left = 0;
tree->L = 0;
return;
}
if (l < tree->label)
addnodeBST(tree->left, l);
if (l > tree->label)
addnodeBST(tree->right, l);
}
int counter(node*tree, int x) {
if (!tree)
return 0;
if ((!tree->left && !tree->right) && ((x % 2 == 0 && tree->label % 2 ==
1) || (x % 2 == 1 && tree->label % 2 == 0)))
return 1;
return counter(tree->left, tree->label) + counter(tree->right, tree-
>label);
}
void updateNode(node*tree) {
if (!tree)
return;
tree->L = counter(tree, 0);
if (!tree->right && !tree->left)
tree->L = 0;
updateNode(tree->left);
updateNode(tree->right);
}
It works, what is not fine are the functions "counter" and "updateNode" together.
"Counter" counts the number of leaves that are to be counted.
"UpdateNode" utilizes "counter" to count and then store the number of leaves in each subtree into L (which i defined in the struct).
This way i have a recursive function into another recursive function and i visit each node multiple times.
How can i optimize my code?
This way i have a recursive function into another recursive function and i visit each node multiple times.
The part before andmakes your code ugly, but the real devil lies in how you chose to traverse the tree.
In your updateNode function, the value of L for a node is simply sum of it's left and right subtree. So instead of calling them at the end of your function (preorder) like you do now, if you call them earlier (postorder); now you know their L and instead of calling counter, you simply add them up. You visit every node exactly once.
You can completely delete your counter function.
Here is modified code (comments explain the code) :
//helper to check leaves, null nodes are not leaf
bool isLeaf(node* tree){
return (tree && (!tree->right) && (!tree->left));
}
//change return type to catch child node's 'L' value through recursive calls
int updateNode(node*tree) {
if (!tree) return 0; //0 for null, for example tree->right for '24'
if (isLeaf(tree)) tree->L = 0; //All the leaves
int a,b;
//find 'L' for left child into a
if(isLeaf(tree->left)){
if(tree->left->label%2!=tree->label%2) a=1; //this will be true for '24' and '10'
else a=0;
}
else a = updateNode(tree->left);
//Now find 'L' for right child into b
if(isLeaf(tree->right)){ //this will be true for '10'
if(tree->right->label%2!=tree->label%2) b=1;
else b=0;
}
else b = updateNode(tree->right);
//combine them
tree->L = a+b; //this will be true for '20'
return tree->L; //return for parent's sake
}
And driver to run it:
void inorder(node* tree){
if(!tree) return ;
inorder(tree->left);
printf("%d : %d %d\n",tree->label,tree->L,isLeaf(tree) );
inorder(tree->right);
}
int main(int argc, char const *argv[])
{
node* tree = 0;
addnodeBST(tree,20);
addnodeBST(tree,10);
addnodeBST(tree,24);
addnodeBST(tree,17);
addnodeBST(tree,23);
addnodeBST(tree,5);
updateNode(tree);
inorder(tree);
return 0;
}
And..your addnodeBST will fail for equal values. Change the second if to else.

Check if only one string variable is not nullptr in C++

I have three LPCWSTR string variables called A, B, C.
I am assigning them from another function which can sometimes return nullptr if something goes wrong. like this:
A = MyFunc();
B = MyFunc();
C = MyFunc();
Now, for some stuff with those variables, I need to check if only one of these variables is not nullptr(only one of variables is assigned).
I tried to do this myself like:
if ((A == nullptr) && (B == nullptr) && (C <> nullptr)) {}
Any ideas about how to do this are welcome.
Easy enough to do with:
int numSet = 0;
A = MyFunc(); if (A != nullptr) numSet++;
B = MyFunc(); if (B != nullptr) numSet++;
C = MyFunc(); if (C != nullptr) numSet++;
if (numSet == 1) // only one is set
You could also encapsulate the behaviour with a helper function:
LPCWSTR MyFuncWithCount(int &countSetProperly) {
LPCWSTR retVal = MyFunc();
if (retVal != nullptr) countSetProperly++;
return retVal;
}
int numSet = 0;
A = MyFuncWithCount(numSet);
B = MyFuncWithCount(numSet);
C = MyFuncWithCount(numSet);
if (numSet == 1) // only one is set
Next step up from there would be using a range-based for loop in conjunction with a braced init list, as per the following complete program:
#include <iostream>
#include <vector>
typedef void * LPCWSTR; // Couldn't be bothered including Windows stuff :-)
int main() {
// Only set two for test purposes.
LPCWSTR A = nullptr, B = nullptr, C = nullptr;
LPCWSTR D = &A, E = nullptr, F = &A;
int numSet = 0;
for (const auto &pointer: {A, B, C, D, E, F})
if (pointer != nullptr)
numSet++;
std::cout << "Count is " << numSet << std::endl;
}
Or you could embrace modern C++ in all its glory by using lambda functions, as per the following:
#include <iostream>
#include <vector>
typedef void * LPCWSTR; // Couldn't be bothered including Windows stuff :-)
int main() {
// Only set two for test purposes.
LPCWSTR A = nullptr, B = nullptr, C = nullptr;
LPCWSTR D = &A, E = nullptr, F = &A;
int numSet = 0;
[&numSet](const std::vector<LPCWSTR> &pointers) {
for (const auto &pointer: pointers)
if (pointer != nullptr)
numSet++;
} (std::vector<LPCWSTR>{A,B,C,D,E,F});
std::cout << "Count is " << numSet << std::endl;
}
That's probably overkill for your particular case however :-)
With std, you may do:
const auto vars = {A, B, C}; // Create initializer list.
const bool onlyOneNotNull =
(std::count(vars.begin(), vars.end(), nullptr) == (vars.size() - 1);
// then you may use find_if to retrieve the non null variable.
Here's one simple way:
int not_null = 0;
not_null += A != nullptr;
not_null += B != nullptr;
not_null += C != nullptr;
if (not_null == 1) {
/* Do stuff */
}
Check each for being nullptr and increment a count if it is not. If the count comes out as 1 in the end, do your thing.
In C++, for backward-compatibility with C, the return value of a relational operator is an int equal to 0 or 1. So you can do:
if ( (a != nullptr) + (b != nullptr) + (c != nullptr) == 1 )
If you want to use logical operators only as logical operators, there are also disjunctive normal form and conjunctive normal form, albeit with more operations.
if ( (a && !b && !c) || (!a && b && !c) || (!a && !b && c) )
if ( (a || b || c) && (!a || !b) && (!a || !c) && (!b || !c) )
The former is not difficult to read in this simple case, compared to most of the other solutions, although it would quickly get too verbose if there were more possible solutions.
You can also stick them in any container, such as a std::array<LPCWSTR, 3>, and do std::count( pointers.begin(), pointers.end(), nullptr) (as Jarod42 suggested).
I'm not a huge fan of using techniques like the following in general, but you can use the fact that for any pointer ptr that !!ptr evaluates to 0 for a null pointer and 1 for a non-null pointer to write
if (!!A + !!B + !!C == 1) {
...
}
as a dense way to get this to work. It's essentially the same as #Davislor's solution but with a more compact "test if null" check.
This approach doesn't scale nearly as well as the accepted approach does, and it's trickier to read, but depending on your audience and who's reading the code it might do the trick nicely.

Strange behaviour of the typeid operator -return FALSE always

This is my part of my code. The question is why using this line return FLASE and i can't get in to his block:
i'm trying to check if my item type is equals to the son.
It's suppose to return true. I see in the debugging it's true also.
if ((typeid(Candy) == typeid(sArray[0])) && (typeid(Candy) == typeid(&item)))
this is my code:
bool Customer::isExistItem(SweetItem& item){
if (Itemsize == 0){
sArray = new SweetItem*[Itemsize + 1];
sArray[Itemsize] = &item;
Itemsize++;
if ((typeid(Candy) == typeid(sArray[0])) && (typeid(Candy) == typeid(&item))){
Candy* help1 = dynamic_cast <Candy*> (sArray[0]);
Candy* help2 = dynamic_cast <Candy*> (&item);
if (*help1 == *help2){ //The first item in the basket!
double payment = 0;
payment += help1->getPrice();
totalPayment(payment);
}
return TRUE;
}
else if ((typeid(Cookie*) == typeid(sArray[0])) && (typeid(Cookie*) == typeid(&item))){
Cookie* help1 = dynamic_cast <Cookie*> (sArray[0]);
Cookie* help2 = dynamic_cast <Cookie*> (&item);
if (*help1 == *help2){ //The first item in the basket!
double payment = 0;
payment += help1->getPrice();
totalPayment(payment);
}
return TRUE;
}
else if ((typeid(IceCream*) == typeid(sArray[0])) && (typeid(IceCream*) == typeid(&item))){
IceCream* help1 = dynamic_cast <IceCream*> (sArray[0]);
IceCream* help2 = dynamic_cast <IceCream*> (&item);
if (*help1 == *help2){ //The first item in the basket!
double payment = 0;
payment += help1->getPrice();
totalPayment(payment);
}
return TRUE;
}
else if ((typeid(Cookielida*) == typeid(sArray[0])) && (typeid(Cookielida*) == typeid(&item))){
Cookielida* help1 = dynamic_cast <Cookielida*> (sArray[0]);
Cookielida* help2 = dynamic_cast <Cookielida*> (&item);
if (*help1 == *help2){ //The first item in the basket!
double payment = 0;
payment += help1->getPrice();
totalPayment(payment);
}
return TRUE;
}
}
this is my == operator that looks ok:
bool Customer::operator ==(const SweetItem& other) const{
for (int i = 0; i < Itemsize; i++){
if (sArray[i] != &other)
return FALSE;
}
return TRUE;
}
please take a look at my code.
The type of both sArray[0] and &item is a SweetItem* pointer, which is never the same as a Candy object.
I guess you want typeid(*sArray[0]) and typeid(item), to examine the dynamic type of the object rather than a more generically typed pointer.

Checking for equality in two lists using == operator

I'm fairly new to C++ and I'm working on a method that will check whether two lists are identical using the == operator. Here's my code as it is right now.
bool List::operator==(const List& original) const {
if(this != &original){
if( mySize != original.getSize() ) { return false; }
unsigned counter = 0;
Node * nPtr = original.myFirst;
Node * myPtr = myFirst;
while (counter < mySize ) {
if( this->myFirst == nPtr ) {
if (counter == 0){
counter++;
nPtr = nPtr->myNext;
}
if (myFirst->myNext == nPtr) {
counter ++;
nPtr = nPtr->myNext;
}
} else {
return false;
}
}
}
return true; }
So, from what I understand, here's what my code is doing. It checks whether their addresses are the same and, if it is, it returns true. Otherwise, it checks to see that their sizes are identical. If not, returns false. If true, goes through the list and checks the different values starting at the first address and going through until it reaches the last one.
However, it's failing this test I wrote and I'm not sure why or how:
List list3;
list3.append(33);
List list4;
list4.append(33); // [33]
assert( list4 == list3 );
assert( list3 == list4 );
cout << " 3 " << flush;
My append method adds a certain value to the list and I've tested it. That method works fine.
I realize this question may be similar to this question already asked but that didn't really help me much. Thanks for any help you can provide!