I want to construct a expression tree for a multi digit number Like given expression is (122+30) and the post order traversal of this gives "122 30 +"
But this code creates the expression tree and gives post order traversal of a single digit expression only like (1+2)
#include <bits/stdc++.h>
using namespace std;
// Tree Structure
typedef struct node
{
char data;
struct node *left, *right;
} * nptr;
// Function to create new node
nptr newNode(char c)
{
nptr n = new node;
n->data = c;
n->left = n->right = nullptr;
return n;
}
unsigned int getOperand(char ch) {
if(ch >= '0' && ch <= '9'){
return ch - '0';
}
return 0;
}
// Function to build Expression Tree
nptr build(string& s)
{
// Stack to hold nodes
stack<nptr> stN;
// Stack to hold chars
stack<char> stC;
nptr t, t1, t2;
// Prioritising the operators
int p[123] = { 0 };
p['+'] = p['-'] = 1, p['/'] = p['*'] = 2, p['^'] = 3,
p[')'] = 0;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '(') {
// Push '(' in char stack
stC.push(s[i]);
}
// Push the operands in node stack
else if (getOperand(s[i]))
{
t = newNode(s[i]);
stN.push(t);
}
else if (p[s[i]] > 0)
{
// If an operator with lower or
// same associativity appears
while (
!stC.empty() && stC.top() != '('
&& ((s[i] != '^' && p[stC.top()] >= p[s[i]])
|| (s[i] == '^'
&& p[stC.top()] > p[s[i]])))
{
// Get and remove the top element
// from the character stack
t = newNode(stC.top());
stC.pop();
// Get and remove the top element
// from the node stack
t1 = stN.top();
stN.pop();
// Get and remove the currently top
// element from the node stack
t2 = stN.top();
stN.pop();
// Update the tree
t->left = t2;
t->right = t1;
// Push the node to the node stack
stN.push(t);
}
// Push s[i] to char stack
stC.push(s[i]);
}
else if (s[i] == ')') {
while (!stC.empty() && stC.top() != '(')
{
t = newNode(stC.top());
stC.pop();
t1 = stN.top();
stN.pop();
t2 = stN.top();
stN.pop();
t->left = t2;
t->right = t1;
stN.push(t);
}
stC.pop();
}
}
t = stN.top();
return t;
}
// Function to print the post order
// traversal of the tree
void postorder(nptr root)
{
if (root)
{
postorder(root->left);
postorder(root->right);
cout << root->data;
}
}
int main()
{
string s ;
getline(cin,s);
nptr root = build(s);
// Function call
postorder(root);
return 0;
}
what changes should I do so that it can handle multi digit expression.
Related
#include <iostream>
#include <string>
using namespace std;
class StackNode
{
public:
StackNode * topPtr = NULL;
StackNode* next;
string item;
bool push( string newItem) {
// create a new node
StackNode *newPtr = new StackNode;
// set data portion of new node
newPtr->item = newItem;
// insert the new node
newPtr->next = topPtr;
topPtr = newPtr;
return true;
}
bool pop() {
if (topPtr == NULL)
return false;
// stack is not empty; delete top
else{
StackNode *temp = topPtr;
topPtr = topPtr->next;
// return deleted node to system
temp->next = NULL; // safeguard
delete temp;
return true;
}
}
int ope(string op, string val1,string val2)
{
int vaL1 = stoi(val1);
int vaL2 = stoi(val2);
int res = 0;
if( op == "*")
res = vaL1 * vaL2;
if( op == "/")
res = vaL1 / vaL2;
if( op == "-")
res = vaL1 - vaL2;
if( op == "+")
res = vaL1 + vaL2;
return res;
}
int cal(string pre_exp[],int len)
{
int numb = 0;
for(int i = len -1;i>=0;i--)
{
if ( pre_exp[i] == "*" || pre_exp[i] == "/" || pre_exp[i] == "+" || pre_exp[i] == "-")
{
string op1 = topPtr->item;
pop();
string op2 = topPtr->item;
pop();
numb = numb + ope(pre_exp[i],op1,op2);
}
else
{
push( (pre_exp[i]));
}
}
return numb;
}
int main()
{
StackNode nbr;
string eyoo[] = {"+","-","2","3","9"};
cout<< nbr.cal(eyoo,5)<<endl;
return 0;
}
Hello everyone, I am trying find the sum of a prefix expression. My code is here. Weirdly, I don't get any output. The method cal does not return the number, probably the program gets stucks in the for loop of the method calc. Can someone help me please? Pop and push methods work, I tested them with a display method. The problem must be in the usage of stoi or in the calc method as I said.
string op1 = topPtr->item;
pop();
string op2 = topPtr->item;
pop();
you always pop the 2 operands of an operator, that supposes you push the result, but you do not do, at a given time topPtr become null, with your example this is when you do string op2 = topPtr->item;
for me numb = numb + ope(pre_exp[i],op1,op2); must be replaced by pushing the result of ope(pre_exp[i],op1,op2) in the stack at the place of the two poped values
so for {"+","-","2","3","9"} :
push 9
push 3
push 2
- so pop=2 - pop=3 = -1, and you have to push -1
+ so pop=-1 + pop=9 = 8 and you push 8 (without the push -1 before the stack is empty when getting the second operand)
all is done so you pop the result = 8
However I am surprised you star by the end of the expression, I am not sure that works in all the case an compute well the result, why you do not start by the beginning ?
A final remark : all your method try to be inline (defined in the class), we use inline when a method is small, better to move the definitions out of the class for your methods
I have a problem with my C++ code. It says that the all the functions starting with isPerfectRec() couldn't be resolved...Why? I tried a lot of things but apparently they don't work. I have a lot of assigments like to verify if the binary search tree is perfect, to find the second largest element in a binary search tree and so on..
#include <stdio.h>
#include<iostream>
#include<stack>
template<typename T> class BinarySearchTree {
public:
BinarySearchTree<T> *root, *left_son, *right_son, *parent;
T *pinfo;
BinarySearchTree() {
left_son = right_son = NULL;
root = this;
pinfo = NULL;
}
void setInfo(T info) {
pinfo = new T;
*pinfo = info;
}
void insert(T x) {
if (pinfo == NULL)
setInfo(x);
else
insert_rec(x);
}
bool isPerfectRec(BinarySearchTree *root, int d, int level = 0)
{
// An empty tree is perfect
if (*root == NULL)
return true;
// If leaf node, then its depth must be same as
// depth of all other leaves.
if (*root->left_son == NULL && root->*right_son == NULL)
return (d == level+1);
// If internal node and one child is empty
if (root->*left_son == NULL || root->*right_son == NULL)
return false;
// Left and right subtrees must be perfect.
return isPerfectRec(root->*left_son, d, level+1) &&
isPerfectRec(root->*right_son, d, level+1);
}
// Wrapper over isPerfectRec()
bool isPerfect(BinarySearchTree *root)
{
int d = findADepth(root);
return isPerfectRec(root, d);
}
int findADepth(BinarySearchTree *node)
{
int d = 0;
while (node != NULL)
{
d++;
node = node->left_son;
}
return d;
}
// A function to find 2nd largest element in a given tree.
void secondLargestUtil(BinarySearchTree *root, int &c)
{
// Base cases, the second condition is important to
// avoid unnecessary recursive calls
if (root == NULL || c >= 2)
return;
// Follow reverse inorder traversal so that the
// largest element is visited first
secondLargestUtil(root->right_son, c);
// Increment count of visited nodes
c++;
// If c becomes k now, then this is the 2nd largest
if (c == 2)
{
std::cout << "2nd largest element is "
<< root->pinfo;
printf("\n___\n");
return;
}
// Recur for left subtree
secondLargestUtil(root->left_son, c);
}
void secondLargest(BinarySearchTree *root)
{
// Initialize count of nodes visited as 0
int c = 0;
// Note that c is passed by reference
secondLargestUtil(root, c);
}
bool hasOnlyOneChild(int pre[], int size)
{
int nextDiff, lastDiff;
for (int i=0; i<size-1; i++)
{
nextDiff = pre[i] - pre[i+1];
lastDiff = pre[i] - pre[size-1];
if (nextDiff*lastDiff < 0)
return false;;
}
return true;
}
BinarySearchTree * readListInter(){
BinarySearchTree* root = NULL;//returning object
BinarySearchTree* temp;
BinarySearchTree* input;//new node to add
int x;
std::cout << "enter number (>0 to stop): ";
std::cin >> x;
while(x>=0){
input = BinarySearchTree(x);
if(root == NULL){//if root is empty
root = input;
temp = root;//temp is use to store value for compare
}
else{
temp = root; //for each new addition, must start at root to find correct spot
while(input != NULL){
if( x < temp->pinfo){//if smaller x to add to left
if(temp->left_son == NULL){//left is empty
temp->left_son = input;
input = NULL;//new node added, exit the loop
}
else{//if not empty set temp to subtree
temp = temp->left_son;//need to move left from the current position
}
}
else{//otherwise x add to right
if(temp->right_son == NULL){//right is empty
temp->right_son = input;
input = NULL;//new node added, exit the loop
}
else{
temp = temp->right_son;//need to move right from the current position
}
}
}
}
std::cin >> x;
}
return root;
}
};
int main() {
BinarySearchTree<int> *r = new BinarySearchTree<int>;
BinarySearchTree<int> *r1 = new BinarySearchTree<int>;
BinarySearchTree<int> *p = new BinarySearchTree<int>;
p = readListInter();
r->insert(6);
r->insert(8);
r->insert(1);
r->insert(9);
r->insert(10);
r->insert(4);
r->insert(13);
r->insert(12);
printf("\n___\n");
r1->insert(6);
r1->insert(8);
r1->insert(1);
r1->insert(9);
r1->insert(10);
r1->insert(4);
r1->insert(13);
r1->insert(12);
printf("\n___\n");
r->isPerfect(r);
int pre[] = {8, 3, 5, 7, 6};
int size = sizeof(pre)/sizeof(pre[0]);
if (hasOnlyOneChild(pre, size) == true )
printf("Yes");
else
printf("No");
s
return 0;
}
I think you need to write BinarySearchTree<T> instead of BinarySearchTree as a datatype in those functions.
I am really stuck in make conversion of special prefix to postfix operation on our task, let me describe the task similarly :
We have such operation to use as operations in our prefixes, here is the method that i am checking them :
bool isOperator(string c)
{
if (c == "log" || c == "exp" || c == "sum" || c == "div" || c == "abs" || c == "sqrt" || c == "sub" || c == "product" || c == "max" || c== "min" || c == "mod" ) // you may add operator here
return true;
return false;
}
Anyway example prefix instructions can have parentheses to make operation precedence, this is what I am stuck at. I know, I need to implement such a recursion, but i can't find a way.
div ( sqrt 5 ) 3
Output should be
5 sqrt 3 div
Another example :
div ( sum ( exp 2 3 ) ( sqrt 5 ) ) 3
Output
2 3 exp 5 sqrt sum 3 div
Every operation, parentheses or number should have space between elements in assumed condition.
My stack implementation
Stack.h
#include<iostream>
using namespace std;
struct node {
string op ;
node *next;
};
struct Stack {
node * head;
void create();
void close();
void push (node *);
node* pop();
node* top();
bool isEmpty();
};
Stack.cpp
#define _CRT_SECURE_NO_WARNINGS
#include "stack.h"
#include <iostream>
#include <stdlib.h>
void Stack::create() {
head = NULL;
}
void Stack::close() {
node *p;
while (head) {
p = head;
head = head->next;
//delete [] p->data;
delete p;
}
}
void Stack::push(node *newdata) {
node *newnode = new node;
newnode = newdata;
newnode->op = newdata->op;
newnode->next = head;
head = newnode;
}
node *Stack::pop() {
if (isEmpty())
return NULL;
node *topnode = head;
head = head->next;
//delete topnode;
return topnode;
}
node *Stack::top() {
if (isEmpty())
return NULL;
node *topnode = head;
//delete topnode;
return topnode;
}
bool Stack::isEmpty() {
return (head == NULL);
}
as #PaulMcKenzie mentioned, i've tried an implementation below, sub_array string array contains the word list without spaces.
bool isLeftParanthesis(string c)
{
if (c == "(" ) // you may add operator here
return true;
return false;
}
bool isRightParanthesis(string c)
{
if (c == ")") // you may add operator here
return true;
return false;
}
int main()
{
string prefix;
getline(cin, prefix);
istringstream iss(prefix);
istringstream iss2(prefix);
int count1 = 0, count2 = 0;
string postfix = "";
Stack *st = new Stack;
string t1, t2;
string sub;
string *sub_array;
while (iss >> sub) {
count1++;
}
sub_array = new string[count1];
while (iss2 >> sub) {
sub_array[count2] = sub;
count2++;
}
int l = count1;
int right_p_count = 0;
for (int i = 0; i < count1; i++)
{
if (isRightParanthesis(sub_array[i]))
{
right_p_count++;
}
}
string *postfixes = new string[right_p_count];
int index_right_p = 0;
for (int i = 0; i < count1; i++) {
while (!isRightParanthesis(sub_array[i]))
{
node *n = new node;
n->op = sub_array[i];
st->push(n);
i++;
if (i == count1)
{
break;
}
}
if( i != count1){
if (isRightParanthesis(sub_array[i])) {
postfix = "";
while (!isLeftParanthesis(st->top()->op))
{
string t = st->pop();
if (!isOperator(t) && !isLeftParanthesis(t) && !isRightParanthesis(t)) {
postfix = t + " " + postfix;
}
else if (isOperator(t)) {
postfix = postfix + " " + t;
}
}
st->pop();
postfixes[index_right_p] = postfix;
index_right_p++;
}
}
postfix = "";
while ( !st->isEmpty() && index_right_p == right_p_count && i == count1)
{
string t = st->pop();
if (!isOperator(t) && !isLeftParanthesis(t) && !isRightParanthesis(t)) {
postfix = t+" "+postfix;
}
else if (isOperator(t)) {
postfix = postfix+""+t;
}
else {
break;
}
}
}
string result = "";
for (int i = 0; i < right_p_count; i++)
{
result = result + "" + postfixes[i];
}
result = result + " " + postfix;
cout << result << endl;
}
Variable postfix refers to output postfix, but my output is not wrong for some of the operations such as :
div ( sqrt 5 ) 3
When i saw a parantheses i am checking if it is left or right, using right one for trigger.
abs ( product -2 -4 -8 )
Expected output is :
-2 -4 -8 product abs
UPDATE : I solved stack problem myself, but found out that, algorithm calculates some expressions wrongly...
Example expression :
3 2 3 exp sum
Expected output :
sum 3 ( exp 2 3 )
My output :
2 3 exp 3 sum
My algorithm which is using right parentheses as triggers calculates it wrongly and I don't know how to implement this control into that, are there any suggestions ?
I've been working on the input from file and think I have the logic right, but my nodes aren't linking properly. I'm able to set the root correctly and the program is able to walk through the string and load the nodes properly, just not link them. Can anyone help me sort through my logic and figure out the problem?
The input string is (A (B (D G) E) (C () F)).
struct node
{
string data;
node* left;
node* right;
};
void tree::build_tree(string &input, int i, node *n)
{
if(i > input.length())
return *n = NULL;
if(input[i] == '(')
{
string data; string temp;
int prev_i = i;
//get_data retrieves the identifier
data = get_data(input, temp, i+1);
//get_data_num retrieves the new position in the string
i = get_data_num(input, temp, i+1);
if(input[prev_i] == '('&& input[i] == ')')
{
i += 1;
*n = NULL;
}
else
{
// Allocate a new node and assign the data and
// set the pointer to the branches to null
*n = new node;
(*n)->data = data;
(*n)->left = NULL;
(*n)->right = NULL;
if(input[i] == ' ')
{i += 1; }
//Pass the address of the nodes
build_tree(input, i, &(*n)->left);
build_tree(input, i, &(*n)->right);
}
}
else if(isalnum(input[i]) || input[i] == '_' || input[i] == '-')
{
string data; string temp;
int prev_i = i;
data = get_data(input, temp, i);
i = get_data_num(input, temp, i);
if(input[prev_i] == '('&& input[i] == ')')
{
i += 1;
*n = NULL;
}
else
{
*n = new node;
(*n)->data = data;
(*n)->left = NULL;
(*n)->right = NULL;
if(input[i] == ' ')
{ i += 1; }
build_tree(input, i, &((*n)->left));
build_tree(input, i, &((*n)->right));
}
}
else if(input[i] == ' ')
{
i += 1;
}
else if(input[i] == ')')
{
i += 1;
*n = NULL;
}
else
{
cout << "The input tree is not in the correct format!" << endl;
}
}
I believe the issue is that you are not setting the value of the left and right pointers. You are passing the values of the pointers. You need to pass a pointer to the pointers (left and right), to set the value in the structure. The other alternative is to use references instead of pointers.
Here are the modifications I came up with for the code you supplied:
Changed the call to build_tree for the node argument be a pointer to
a pointer.
Changed assignments of values accordingly.
Changed call to build_tree to pass the address of left and right (to
get a pointer to a pointer).
Remove the assignment/conditions to set the root_node. So when you
call the build_tree you need to pass in the address of root. This
will set the node just like all of the nodes which follow, so it does not need
to be a special case.
Added assignment of NULL for left and right in case there is not a
branch (may not need to do this, but I feel it is good practice to
make sure all items have some initial values).
void tree::build_tree(string &input, int i, node **n)
{
if(input[i] == '(')
{
string data; string temp;
//get_data retrieves the identifier
data = get_data(input, temp, i+1);
//get_data_num retrieves the new position in the string
i = get_data_num(input, temp, i+1);
// Allocate a new node and assign the data and
// set the pointer to the branches to null
*n = new node;
(*n)->data = data;
(*n)->left = NULL;
(*n)->right = NULL;
if(input[i] == ' ')
{ i += 1; }
// Pass the address of the nodes
build_tree(input, i, &(*n)->left);
build_tree(input, i, &(*n)->right);
}
else if(isalnum(input[i]) || input[i] == '_' || input[i] == '-')
{
string data; string temp;
data = get_data(input, temp, i);
i = get_data_num(input, temp, i);
*n = new node;
(*n)->data = data;
(*n)->left = NULL;
(*n)->right = NULL;
if(input[i+1] == ' ')
{ i += 1; }
build_tree(input, i, &((*n)->left));
build_tree(input, i, &((*n)->right));
}
else if(input[i] == ' ')
{
i += 1;
}
else if(input[i] == ')')
{
*n = NULL;
}
else
{
cout << "The input tree is not in the correct format!" << endl;
}
}
Then for the initial call,
build_tree(testString,0,&root);
Since the get_data and get_data_num were not supplied, I was not able to test the changes which were made.
so heres my header and cpp file.
template<typename T> struct TreeNode
{
TreeNode(const T& value, TreeNode<T>* left = NULL, TreeNode<T>* right = NULL)
{
Value = value;
Left = left;
Right = right;
}
T Value;
TreeNode<T>* Left;
TreeNode<T>* Right;
bool IsLeaf() const
{
return Left == NULL && Right == NULL;
}
};
and now my cpp file
#include "TreeNode.h"
#include <iostream>
#include <string>
using namespace std;
float ValueOf(TreeNode<char>* root);
float ValueOf(TreeNode<char>* root)
{
if (root->IsLeaf())
return root->Value - '0';
float expressionValueL = ValueOf(root->Left);
float expressionValueR = ValueOf(root->Right);
if (root->Value == '+')
return expressionValueL+expressionValueR;
else if (root->Value == '-')
return expressionValueL-expressionValueR;
else if (root->Value == '*')
return expressionValueL*expressionValueR;
else if (root->Value == '/')
return expressionValueL/expressionValueR;
}
void main ()
{
TreeNode<char>* treeRoot = nullptr;
TreeNode<char>* currentNode = treeRoot;
string expr;
cout<<"please input expression to be tested:";
getline (cin, expr);
cout<<endl;
int size = expr.size();
for (int i=0; i<size; i++)
{
char test = expr[i];
if ((test=='1')||(test=='0')||(test=='2')||(test=='3')||(test=='4')||(test=='5')||(test=='6')||(test=='7')||(test=='8')||(test=='9'))
{
TreeNode<char> newLeaf = (expr[i]);
if (currentNode == nullptr)
{
treeRoot=&newLeaf;
currentNode = &newLeaf;
}
else
currentNode->Right = &newLeaf;
}
else if ((expr[i]=='+')||(expr[i]=='-'))
{
TreeNode<char> newRoot = test;
newRoot.Left = treeRoot;
treeRoot = &newRoot;
currentNode = &newRoot;
}
else if (((expr[i]=='*')||(expr[i]=='/'))&&(currentNode->Right==nullptr))
{
TreeNode<char> newRoot = test;
newRoot.Left = treeRoot;
treeRoot = &newRoot;
currentNode = &newRoot;
}
else if (((expr[i]=='*')||(expr[i]=='/'))&&(currentNode->Right!=nullptr))
{
TreeNode<char> newChild = test;
newChild.Left = currentNode->Right;
currentNode->Right = &newChild;
currentNode = &newChild;
}
}
cout<<ValueOf(treeRoot)<<endl;
system("pause");
}
the problem is that every time i run it, and i input something like 3*4-2, all of the digits in the tree gets overwritten to what the last digit inserted was, so its interpreted as 2*2-2 and gives me 2 as an answer, instead of 10 can anyone tell me what my problem is? thanks =).
btw this program assumes wellformed expressions and single digit numbers.
TreeNode<char> newLeaf = (expr[i]); creates an object on stack - it's invalidated when you leave the enclosing scope. You should not store pointers to such objects.
Use TreeNode<char> * newLeaf = new TreeNode<char>(expr[i]); - and corresponding for any other node that you assign to ->Right and ->Left - aka need to keep alive beyond the scope where you create them.
As mentioned by Erik,
TreeNode<char> newLeaf = (expr[i]);
is a local stack variable; instead of do following:
TreeNode<char> *newLeaf = new TreeNode<char>(expr[i]);
And then assign to proper leg. Also, below condition,
if ((test=='1')||(test=='0')||(test=='2')||(test=='3')||(test=='4')||(test=='5')||(test=='6')||(test=='7')||(test=='8')||(test=='9'))
Can be squeezed to,
if(test >= '0' && test <= '9')
In the same way, you can also co-relate the last two else if() statements for better code