Parsing boolean expression and creating binary tree in C++ - c++

I am working on a code which should parse a boolean expression and load it into a binary tree.
However I'm confused about how I should start adding node to the tree.
If I have an expression like: a AND b OR C then I should end up with the following tree:
AND
a OR
b c
I found following example which explains how to create a binary tree but not sure how I can modify this to work with boolean expression.
class btree
{
public:
btree();
~btree();
void insert(int key);
node *search(int key);
void destroy_tree();
private:
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
node *search(int key, node *leaf);
node *root;
};
void btree::insert(int key)
{
if(root!=NULL)
insert(key, root);
else
{
root=new node;
root->key_value=key;
root->left=NULL;
root->right=NULL;
}
}
void btree::insert(int key, node *leaf)
{
if(key< leaf->key_value)
{
if(leaf->left!=NULL)
insert(key, leaf->left);
else
{
leaf->left=new node;
leaf->left->key_value=key;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else if(key>=leaf->key_value)
{
if(leaf->right!=NULL)
insert(key, leaf->right);
else
{
leaf->right=new node;
leaf->right->key_value=key;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
}
I need some pointers on how to get started since I have never done it before.
What should the basic algorithm for the insert function look like? I didn't find any similar examples on line.

Related

Not able to traverse elements in Binary search tree in C++

I am trying to print all the elements using inorder traversal, but my code is giving incorrect output. I am not able to figure out what went wrong.
#include <iostream>
using namespace std;
struct node
{
int value;
struct node * left;
struct node * right;
};
class Btree
{
node * root;
void insert(int value, node * leaf);
node * search(int value, node * leaf);
void destroy(node * leaf);
public:
Btree() { root = NULL; }
~Btree() { destroy(); }
void insert(int value);
node * search(int value);
void destroy();
void inorder(node * ptr);
};
void Btree::inorder(node *ptr)
{
if (ptr != NULL)
{
inorder(ptr->left);
cout << ptr->value << "";
inorder(ptr->right);
}
}
void Btree::destroy(node *leaf)
{
if(leaf!=NULL)
{
destroy(leaf->left);
destroy(leaf->right);
delete leaf;
}
}
void Btree :: destroy()
{
destroy(root);
}
node *Btree::search(int value, node *leaf)
{
if(leaf!=NULL)
{
if(value==leaf->value)
return leaf;
if(value<leaf->value)
return search(value, leaf->left);
else
return search(value, leaf->right);
}
else return NULL;
}
node *Btree::search(int value)
{
return search(value, root);
}
void Btree::insert(int value, node *leaf)
{
if(value< leaf->value)
{
if(leaf->left!=NULL)
insert(value, leaf->left);
else
{
leaf->left=new node;
leaf->left->value=value;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else if(value>=leaf->value)
{
if(leaf->right!=NULL)
insert(value, leaf->right);
else
{
leaf->right=new node;
leaf->right->value=value;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
}
void Btree::insert(int value)
{
if(root!=NULL)
insert(value, root);
else
{
root=new node;
root->value=value;
root->left=NULL;
root->right=NULL;
}
}
int main()
{
Btree bst;
struct node * root = NULL;
root = new node;
bst.insert(10);
bst.insert(6);
bst.insert(14);
bst.insert(3);
bst.insert(8);
bst.insert(7);
bst.insert(9);
bst.insert(5);
bst.inorder(root);
return 1;
}
I have tried to create a memory pointer that is the root and then passing that root in my inorder function call. My inorder should print me the output
3 5 6 7 8 9 10 14
A pointer to a step-debugger would help me in solving the issue I believe.Or if anyone can provide me the corrected code, would be quite helpful
Edit:- I had previously passed ptr but used root in my inorder function definition (due to which I was getting Bus error), but now it is correected. However, I still do not get the right output. The output I get is 0

Not able to add value of the matrix to the child of the node three

I have got a matrix which has random values inside. The values range from 1 to Width-1. My decision is to use trees with 4 children per parent (up, right, down, left). The right function checks if the value of the matrix's cell is less than the Width+Value, if yes then it should be possible to save cell's value into the right child of a node iş being holded, then check for the next values recursively. In the end of the recursional process, return to down,left and up functions which work the same way as up. The last destionation is b[HEIGHT-1][WIDTH-1] point. For Example:
2 1 21 2 11 1 2
This matrix should fort a tree:
The code I use has been edited and taken from binary tree.
struct node
{
int key_value;
node *left;
node *right;
node *down;
node *up;
};
class btree
{
public:
btree();
~btree();
void insert(int key); //edit
node *search(int key);
void destroy_tree();
void destroy_tree(node *leaf);
void insert(int key, node *leaf, int position);
node *root;
};
btree::btree()
{
root=NULL;
}
btree::~btree()
{
destroy_tree();
}
void btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
destroy_tree(leaf->up);
destroy_tree(leaf->down);
delete leaf;
}
}
void btree::insert(int key)//set root (start point b[0][0])
{
root=new node;
root->key_value=key;
root->left=NULL;
root->right=NULL;
root->up=NULL;
root->down=NULL;
cout<<"root value"<<root->key_value;
}
void btree::insert(int key, node *leaf, int position) //up 1,right 2, down 3, left 4
{
if(position==1)
{
if(leaf->up!=NULL)
insert(key, leaf->up,1);
else
{
leaf->up=new node;
leaf->up->key_value=key;
leaf->up->up=NULL; //Sets the up child of the child node to null
leaf->up->down=NULL; //Sets the down child of the child node to null
leaf->up->left=NULL; //Sets the left child of the child node to null
leaf->up->right=NULL; //Sets the right child of the child node to null
}
}
else if(position==2)
{
if(leaf->right!=NULL)
insert(key, leaf->right,2);
else
{
leaf->right=new node;
leaf->right->key_value=key;
leaf->right->up=NULL; //Sets the up child of the child node to null
leaf->right->down=NULL; //Sets the down child of the child node to null
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
else if(position==3)
{
if(leaf->down!=NULL)
insert(key, leaf->down,3);
else
{
leaf->down=new node;
leaf->down->key_value=key;
leaf->down->up=NULL; //Sets the up child of the child node to null
leaf->down->down=NULL; //Sets the down child of the child node to null
leaf->down->left=NULL; //Sets the left child of the child node to null
leaf->down->right=NULL; //Sets the right child of the child node to null
}
}
else if(position==4)
{
if(leaf->left!=NULL)
insert(key, leaf->left,4);
else
{
leaf->left=new node;
leaf->left->key_value=key;
leaf->left->up=NULL; //Sets the up child of the child node to null
leaf->left->down=NULL; //Sets the down child of the child node to null
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else{
cout<<"ERROR insert node"<<endl;
}
}
void btree::destroy_tree()
{
destroy_tree(root);
}
signed short int check;
void up(int b[][WIDTH], int x, int y){
check=y-b[x][y];// check if there is space to go up
if (check<0){ // if yes
// go to right() function
}
else{ // if there is place recurse and save the pass to the up leaf
}
}
void down(int b[][WIDTH], int x, int y){}
void right(int b[][WIDTH], int x, int y){
check=y+b[x][y];// check if there is space to go right
if (check>WIDTH){ // if no go to down function
down(b,x,y);
}
else{ // if there is place recurse and save the pass to the up leaf
btree::insert(b[x][check], leaf->left, 2); // save the value of the node b[x][check] into the right child
right(b,x,y+check);
cout<<"value of the node:"<<endl;
}
}
void left(int b[][WIDTH], int x, int y);
int main(){
int b[HEIGHT][WIDTH], row, col;
for (row = 0; row <=HEIGHT-1; row++)
for (col = 0; col <=WIDTH-1; col++)
cin >> b[row][col];
btree start;
start.insert(b[0][0]);
return 0;
}
I get the error leaf was leaf was not declared but leaf->right was ment to send the right leaf of the root (in the beginning), and other children lately.
This was the solution:
btree up;
up.insert(b[x][check], leaf->up, 2, x, y);
to create an object.

Problems with rotations when converting a BST (no recursion) to AVL

I'm working on a university project (Data structures) this weekend and I have to code an AVL tree in C++. I thought that it wouldn't be difficult to code a BST first and then convert it into an AVL. Probably I was wrong... I have two classes, class node and class AVLTree,which is friend of class node. I managed to do the insertions and deletions according to BST's rules (I checked) and also I managed to find the balance factor of its node of the tree (which also worked). However, when I tried the simple left rotations, everything went out of order! Here's my code (first the .h files):
class node
{
public:
node();
private:
int data;
int heightL;
int heightR;
int balance;
node* leftChild;
node* rightChild;
friend class AVLTree; //Only class AVLTree has now access to the private fields of class node
};
class node;
class AVLTree
{
public:
AVLTree();
bool insertNode(int aData);
node* searchNode(int key);
bool deleteNode(int key);
node* findMostLeft(node *aRoot);
node* findMostRight(node *subtree);
void display();
private:
node *root;
void inOrderTraversal(node* pointer);
node* newNode(int aData);
void updateHeightsInserting(int nodeCounter,int aData);
void updateHeightsDeleting(int nodeCounter,int aData);
void updateTreeHeights(node *ptr);
int max(int a,int b);
void balanceTree(node *current,node *previous,node *next);
void slRotation(node* current,node *previous,node *next);
void srRotation(node* current,node *previous,node *next);
void dlRotation(node* current,node *previous,node *next);
void drRotation(node* current,node *previous,node *next);
};
And now the .cpp file of class AVLTree (some methods only)
bool AVLTree::insertNode(int aData)
{
node *current,*next,*ptr;
bool isLeftChild;
int nodeCounter=0;
current=next=root;
ptr=newNode(aData);
if(ptr==NULL) //Couldn't allocate memory
{
return false;
}
if(current==NULL) //Inserting the first node in our tree (root==NULL)
{
root=ptr;
return true; //Successful insertion of root
}
do
{
if(aData<current->data) //If the node we want to insert has data smaller than the current node's data, then repeat the procedure for the left child of the current node
{
next=current->leftChild;
isLeftChild=true;
nodeCounter++;
}
else if(aData>current->data) //If the node we want to insert has data bigger than the current node's data, then repeat the procedure for the right child of the current node
{
next=current->rightChild;
isLeftChild=false;
nodeCounter++;
}
if(next==NULL)
{
if(isLeftChild)
{
current->leftChild=ptr;
}
else
{
current->rightChild=ptr;
}
updateHeightsInserting(nodeCounter,aData);
return true;
}
current=next; //Repeat the procedure for the next node
}while(next!=NULL); //Repeat the procedure until there's no next node, meaning we enter the if(next==NULL) statement
}
The method for updating heights:
void AVLTree::updateHeightsInserting(int nodeCounter,int aData)
{
node *current,*next,*previous;
current=next=previous=root;
do
{
if(aData<current->data)
{
if(current->heightL<nodeCounter)
{
current->heightL=nodeCounter;
}
next=current->leftChild;
nodeCounter--;
}
else if(aData>current->data)
{
if(current->heightR<nodeCounter)
{
current->heightR=nodeCounter;
}
next=current->rightChild;
nodeCounter--;
}
current->balance=current->heightR-current->heightL;
if(abs(current->balance)>1)
{
if(abs(next->heightR-next->heightL)<1) //We use <1, because the hight of the next node hasn't been increased yet-If the next node isn't problematic it means the current node is
balanceTree(current,previous,next);
}
previous=current;
current=next;
}while(next->data!=aData);
}
A trial code for rotation (It doesn't work!)
void AVLTree::slRotation(node *current,node *previous,node *next)
{
if(current==root) //previous=current
{
node *temp;
root=next; //next=current->rightChild
temp=next->leftChild;
next->leftChild=current;
current->rightChild=temp;
}
else
previous->rightChild=next;
current->rightChild=NULL;
next->leftChild=current;
}
And the Balancing method:
void AVLTree::balanceTree(node *current,node *previous,node *next)
{
if(current->balance>1) //if the tree is right heavy
if(next->balance>0) //if the tree's right subtree is right heavy
slRotation(current,previous,next); //perform Simple Left Rotation
else //if the tree's right subtree is left heavy
dlRotation(current,previous,next); //perform Double Left Rotation
else //if the tree is left heavy
if(next->balance<0) //if the tree's left subtree is left heavy
srRotation(current,previous,next); //perform Simple Right Roation
else //if the tree's left subtree is right heavy
drRotation(current,previous,next); //perform Double Right Rotation
updateTreeHeights(root);
}
I also use the updateTreeHeights (this is tested, too and works well without the rotations) method here that isn't efficient, I know, but I didn't have a better idea!
void AVLTree::updateTreeHeights(node *ptr) //Visits the nodes by level recursively (post-order traversal), so that it can calculate the balance of each node
{
if(ptr==NULL)
return;
updateTreeHeights(ptr->leftChild);
updateTreeHeights(ptr->rightChild);
if(ptr->leftChild==NULL && ptr->rightChild==NULL)
{
ptr->heightL=ptr->heightR=0;
}
else if(ptr->leftChild==NULL)
{
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
ptr->heightL=0;
}
else if(ptr->rightChild==NULL)
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=0;
}
else
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
}
ptr->balance=ptr->heightR-ptr->heightL;
}
Sorry for the long post! It's the first time in my life I use an AVL tree, let alone programming it! Hope you can help!
Problem solved! I messed up with the right and left pointers in double rotations!

Undefined reference to main from crt1.o

Error Message:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
struct node
{
int key_value;
node *left;
node *right;
};
class btree
{
public:
btree();
~btree();
void insert(int key);
node *search(int key);
void destroy_tree();
private:
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
node *search(int key, node *leaf);
node *root;
};
btree::btree()
{
root=NULL;
}
void btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void btree::insert(int key, node *leaf)
{
if(key< leaf->key_value)
{
if(leaf->left!=NULL)
insert(key, leaf->left);
else
{
leaf->left=new node;
leaf->left->key_value=key;
leaf->left->left=NULL; //Sets the left child of the child node to null
leaf->left->right=NULL; //Sets the right child of the child node to null
}
}
else if(key>=leaf->key_value)
{
if(leaf->right!=NULL)
insert(key, leaf->right);
else
{
leaf->right=new node;
leaf->right->key_value=key;
leaf->right->left=NULL; //Sets the left child of the child node to null
leaf->right->right=NULL; //Sets the right child of the child node to null
}
}
}
node *btree::search(int key, node *leaf)
{
if(leaf!=NULL)
{
if(key==leaf->key_value)
return leaf;
if(key<leaf->key_value)
return search(key, leaf->left);
else
return search(key, leaf->right);
}
else return NULL;
}
void btree::insert(int key)
{
if(root!=NULL)
insert(key, root);
else
{
root=new node;
root->key_value=key;
root->left=NULL;
root->right=NULL;
}
}
node *btree::search(int key)
{
return search(key, root);
}
void btree::destroy_tree()
{
destroy_tree(root);
}
Can anyone tell me where this error message is coming from so I can attempt to fix it? I'm trying to understand nodes better by running programs using nodes, and this error message is thrown.
As the error message says you are missing a main function. Every program needs a main function, that's where the program starts (more or less). What were you expecting this program to do?

Deleting the entire binary search tree at once

I have been trying to implement the delete BST function but I don't know why it is not working, I think it's logically correct. Can any body please tell me, why I'm getting run time error and how should I correct it.
#include <iostream>
using namespace std;
class node{
public:
int data;
node *right;
node *left;
node(){
data=0;
right=NULL;
left=NULL;
}
};
class tree{
node *head;
int maxheight;
public:
tree(){head=0;maxheight=-1;}
bool deletenode(int key,node* root);
int get_height(){return maxheight;}
void insert(int key);
void pre_display(node* root);
void delete_tree(node *root);
node* get_head(){return head;}
};
void tree::insert(int key){
node *current=head;
node *newnode=new node;
if(newnode==NULL)
throw(key);
newnode->data=key;
int height=0;
if(head==0){
head=newnode;
}
else
{
while(1){
if(current->right==NULL && current->data < newnode->data)
{
current->right=newnode;
height++;
break;
}
else if(current->left==NULL && current->data > newnode->data)
{
current->left=newnode;
height++;
break;
}
else if(current->right!=NULL && current->data < newnode->data)
{
current=current->right;
height++;
}
else if(current->left!=NULL && current->data > newnode->data)
{
current=current->left;
height++;
}
}
}
if(height>maxheight)
maxheight=height;
}
void tree::pre_display(node *root){
if(root!=NULL)
{
cout<<root->data<<" ";
pre_display(root->left);
pre_display(root->right);
}
}
void tree::delete_tree(node *root){
if(root!=NULL)
{
delete_tree(root->left);
delete_tree(root->right);
delete(root);
if(root->left!=NULL)
root->left=NULL;
if(root->right!=NULL)
root->right=NULL;
root=NULL;
}
}
int main(){
tree BST;
int arr[9]={17,9,23,5,11,21,27,20,22},i=0;
for(i=0;i<9;i++)
BST.insert(arr[i]);
BST.pre_display(BST.get_head());
cout<<endl;
BST.delete_tree(BST.get_head());
BST.pre_display(BST.get_head());
cout<<endl;
system("pause");
return 0;
}
All the other functions are working correctly, you just need to check the delete_tree function, the other code is provided to give the idea of the structure of my BST.
In your delete_tree
void tree::delete_tree(node *root){
if(root!=NULL)
{
delete_tree(root->left);
delete_tree(root->right);
delete(root);
if(root->left!=NULL)
root->left=NULL;
if(root->right!=NULL)
root->right=NULL;
root=NULL;
}
}
you are accessing root variable after you have deleted it
Also you call
BST.delete_tree(BST.get_head());
BST.pre_display(BST.get_head());
pre_display after deleting tree. delete_tree after deleting the tree should also set the BST.head to NULL
Also a critique. BST is of type tree. It already has a head member variable indicating the root node. So delete_tree/pre_display do not need any parameters at all.
You can delete by:
//This is function of cleaning:
void cleantree(tree *root){
if(root->left!=NULL)cleantree(root->left);
if(root->right!=NULL)cleantree(root->right);
delete root;}
//This is where we call the cleaning function:
cleantree(a);
a=NULL;
//Where "a" is pointer to root of the tree.
The problem is here:
delete_tree(root->left);
delete_tree(root->right);
delete(root);
if(root->left!=NULL)
root->left=NULL;
if(root->right!=NULL)
root->right=NULL;
root=NULL;
You're trying to assign NULL to a member of root:
root->left=NULL;
which was already deleted. There's no need to do that since you're already freeing the memory in delete_tree(root->left);
Recursively delete left and right sub tree and your tree will be deleted as simple as:
void delete(node *root){
// If node is empty, don't bother
if (root == NULL) { return; }
// Delete subtrees
delete(root->left);
delete(root->right);
// Delete current node
free(root);
root = NULL;
}
You should not read from root after deleting it. Move the delete(root) line down.
Short answer: your implementation of the node descriptor missing the correct explicit destructor implementation (the default generated by the compiler will be used by calling the delete operator:calling destructor and releasing the allocated space on the heap)-the one that clear references to the siblings
here is my suggestion using recursivity..
template <class T> void Tree<T>::destroy(Noeud<T> ** r){
if(*r){
if(!(*r)->left && !(*r)->right){ //a node having no child
delete *r; *r=NULL;
}else if((*r)->left && (*r)->right){ //a node having two childs
destroy(&(*r)->left); //destroy the left tree
destroy(&(*r)->right); //destroy the right tree
destroy(r); //destroy the node
}else if((*r)->left){ //a node has only left child
destroy(&(*r)->left); //destroy the left tree
destroy(r); //destroy the node
}else if((*r)->right){ //a node has only right child
destroy(&(*r)->right); //destroy the right tree
destroy(r); //destroy the node
}
}
}
//in function main()
int main(){
Tree<int> a(5); // 'a' is a tree of int type with a root value equal 5
a.add(2);a.add(7);a.add(6);a.add(-1);a.add(10); // insert values into the tree
a.destroy(&a.root); //destroy the tree
}