Expression evaluation based on binary tree (C + +, detailed idea)

Keywords: C++ data structure Binary tree

describe

Enter an expression (the numbers in the expression are positive integers less than 10), use a binary tree to represent the expression, create an expression tree, and then use the traversal operation of the binary tree to find the value of the expression.

input

Multiple sets of data. Each row of data is an expression, which ends with '='. When only one "=" is entered, the input ends.

output

Each group of data outputs a row, which is the value of the expression.

Input sample 1  

2*(2+5)=
1+2=
=

Output sample 1

14

Idea:

In the past, when using the stack, the idea was to establish a stack for the operator and a stack for the operand, and input and output according to the operation. This time it is done with a Tree. It still involves the elastic stack of numbers, but this number is stored in the Tree node. Each node may store numbers or characters, so it is still two stacks. One Stores operators and the other stores a Tree node instead of numbers, which is convenient for building a Tree.

When I do this, I feel that the main problem of this problem is where the established tree is established and how to find the root node. An empty tree is bound to be initialized in the main function, so do you use it to build a tree when you encounter a node? What if it is a leaf node? Many problems are very confused, and even don't know how to describe them in language.

The Build function is a process of traversing and building a tree. At the beginning, we used string to receive, and then traversed characters one by one to perform corresponding operations, but they all changed greatly later, because traversing a complete formula for does not mean that the tree has been established. It can be thought that if operations are required between values, or the results of operations need to be stored, the tree needs to be established continuously, Until no results need to be added to the tree, and the way of string traversal cannot know when the process ends, so we can only enter characters one by one and judge them every time.

The RUOptr function determines whether the character at the current position is an operator.

The CreateTree function is used to create a tree. Here we are going to solve a big problem: does the final btree used by the main function to output be created into this function? The answer is no, it is not the target object of CreateTree, that is, CreateTree actually creates a node in its own function with the current character, creates it together with the values of its two child nodes, returns this node, and will be processed later. Because the tree in our main function must be the root node of the tree finally built, and cannot be casually equal to any other node; At the same time, the tree creation algorithm is not recursive!!! Think about it. You don't know what the next node is (number or symbol), so you don't know the relationship between the next node and it; I don't know my position. How can I recurse? Don't be framed by ppt and textbooks, let alone copy the code above... The lesson is really painful...

Now that we have a node containing a number, what should we do? The answer is: I don't know how to do it. Because a simple digital node is meaningless, it can only have an operational relationship with other digital nodes when it meets an operator, and form a small tree centered on the operator. Therefore, it is useless now. Put it on the stack first. Don't assign a value to the btree of the main function!!

Then judge the next character again. cmp is a function used to prioritize the operator. If the operator is the same as before, it will be put on the stack if it has a higher priority than the top of the stack. If it is') 'or' = 'it will be out of the stack. Equality (operation) is the key!! At this time, two numbers pop up from the tree node stack for operation. Due to the operator, the op of CreateTree and temp is given to it, and the left and right children also know (the two numbers just popped up). This is equivalent to establishing a small tree. Note at this time: the btree in our main function can be assigned! For example, if the formula 1 + 2 = is completed now, bt should point to that + right, so popularize it. The root created each time is what btree should be =.

Calculate and Operate are the process of traversing the tree to calculate. At this time, you can recurse because the tree has been established.

I feel this question is beyond my current level.. I hope this article can make myself understand and readers understand..

code:

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<map>
using namespace std;

typedef struct BNode
{
	int num;
	char op;
	struct BNode* lchild, * rchild;
}*BTree, BNode;
typedef struct TreeNode
{
	BTree data;
	struct TreeNode* next;
}*Tstack, TNode;
typedef struct OptrNode
{
	char optr;
	struct OptrNode* next;
}*Ostack, ONode;
char PopNoPrint(Ostack& os)
{
	if (os)
	{
		char temp = os->optr;
		Ostack t = os;
		os = os->next;
		delete t;
		//No printing, return value
		return temp;
	}
}
char TOP(Ostack os)
{
	if (os)	return os->optr;
}
BTree PopNoPrint(Tstack& ts)//Change the return value to BTree
{
	if (ts)
	{
		BTree temp = ts->data;
		Tstack t = ts;
		ts = ts->next;
		delete t;
		//No printing, return value
		return temp;
	}
}
void InitStack(Ostack& os,Tstack& ts)
{
	os = NULL;
	ts = NULL;
}
BTree CreateTree(char c, BTree& l, BTree& r)
{
	//Changed, not bt = new BNode;
	BTree temp = new BNode;
	temp->op = c;
	temp->lchild = l;
	temp->rchild = r;
	return temp;
}
BTree CreateTree(int a, BTree& l, BTree& r)
{
	//Changed, not bt = new BNode;
	BTree temp = new BNode;
	temp->num = a;
	temp->lchild = l;
	temp->rchild = r;
	return temp;
}
void InStack(Ostack& os,char c)//Operator stack
{
	Ostack temp = new ONode;
	temp->optr = c;
	temp->next = NULL;
	temp->next = os;
	os = temp;
}
void InStack(Tstack& ts, BTree bt)//Tree stack
{
	Tstack temp = new TNode;
	temp->data = bt;
	temp->next = ts;
	ts = temp;
}
int RUOptr(char ch)	//Judge whether the read character ch is an operator
{
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')' || ch == '=')
		return true;
	else return false;
}
int cmp(char a,char b)//Comparison operator priority
{
	if (a == '*' || a == '/')
	{
		if (b == '(')
			return -1;
		else
			return 1;
	}
	if (a == '+' || a == '-')
	{
		if (b == '*' || b == '/' || b == '(')
			return -1;
		else
			return 1;
	}
	if (a == '(')
		if (b == ')')
			return 0;
		else return -1;

	if (a == '=')
		if (b == '=')
			return 0;
		else
			return -1;
	else return 1;
}
int Operate(int a, char theta, int b)
{
	switch (theta)
	{
	case '+':return a + b; break;
	case '-':return a - b; break;
	case '*':return a * b; break;
	case '/':return a / b; break;
	default:break;
	}
}
int Calculate(BTree bt)
{
	if (!bt)
		return 0;
	if (!bt->lchild && !bt->rchild)
	{    //The left and right subtrees are empty, indicating that the node is a number and needs operation
		return bt->num;
	}
	else
	{
		int lvalue=0, rvalue=0;
		lvalue = Calculate(bt->lchild);
		rvalue = Calculate(bt->rchild);
		return Operate(lvalue, bt->op, rvalue);
	}
}
void Build(BTree& bt)
{
	Tstack t;
	Ostack o;
	InitStack(o, t);
	InStack(o, '=');
	char c;
	cin >> c;
	if (c == '=')
		exit(0);
	while (TOP(o) != '='||c!='=')
	{
		if (!RUOptr(c))//Not an operator
		{
			BTree temp = NULL;//This sentence!
			InStack(t, CreateTree(c-'0', temp, temp));
			cin >> c;
		}
		else//Is operator
		{
			if (cmp(TOP(o), c)==-1)//Priority over current character
			{
				InStack(o, c);//Push 
				cin >> c;
			}
			else if(cmp(TOP(o),c)==1)//The bullet symbol and bullet number are calculated and put on the stack
			{	//If we can improve here
				BTree x = new BNode, y = new BNode;
				x = PopNoPrint(t), y = PopNoPrint(t);
				BTree root = CreateTree(PopNoPrint(o), x, y);
				InStack(t, root);
				bt = root;
			}
			else//Is' = ', indicating that one is' (' one is') '
			{
				PopNoPrint(o);//'(' out of stack
				cin >> c;
			}
		}
	}
}

int main()
{
	while (1)
	{
		BTree b;
		Build(b);
		cout << Calculate(b) << endl;
	}
	return 0;
}
 
     

Posted by tejama on Tue, 30 Nov 2021 14:23:22 -0800