这次是某人的课程作业,题目不难,但是很复杂
原题如下
以字符序列的形式从键盘输入不含变量的整数算术四则表达式(可以有小括号);
检查表达式的正确性
将其转换为二叉树的存储表示;
通过后序遍历得到其后缀表达式序列,输出该序列;
利用后缀表达式进行求值运算,输出求值结果
原本按照我的思路,先求后缀表达式在求值与生成树,不过既然题目这么说了,就不得不按照题目要求去做......
1.表达式的正确性
原本的思路是做正则表达式,在利用包或者是自己写一个自动机去实现,不过发现这里面的正则表达式有一点小复杂.后来在网上找到了递归下降分析法的思路,就正好最近也在写编译原理的题目,刚好把词法分析器办过来用.
原网址如下点击打开链接
2.二叉树生成
二叉树的生成和后缀表达式的求值其实是很相似的,都是利用两个栈,反复比较两个栈的内容,进行求值,只是一个是显示数值,另外一个这是构造节点.在数据结构的书中讲述过后缀表达式的算法,在这里就不赘述了
最后提供
#include <iostream>
#include <vector>
#include <string>
#include <utility>
#include<stack>
using namespace std;
enum Type
{
Other, Add, Sub, Mul, Div, Num, LetfBra, RightBra
};
typedef pair<string, Type> Tocken;
vector<Tocken> word;
struct Node
{
string oper;//操作数或运算符
Node *left;//左子树
Node *right;//右子树
};
int idx = Other;
Type sym;
int err = 0; // 错误
void E();
void E1();
void T();
void T1();
void F();
void PutIn(string& expr);
bool isOper(char op)
{
return op == '+' || op == '-' || op == '*' || op == '/' || op == '(' || op == ')';
}
//求运算符的优先级
int getOperPri(char op)
{
switch (op)
{
case '(':
return 1; break;
case '+':
case '-':
return 2; break;
case '*':
case '/':
return 3; break;
default:
return 0;
}
}
//销毁二叉树
void freeTree(Node*& p)
{
if (p->left != NULL)
freeTree(p->left);
if (p->right != NULL)
freeTree(p->right);
delete(p);
}
//表达式生成二叉树
void generateTree(Node*& p, vector<Tocken> WordArray)
{
stack <char> operStack;
stack <Node*> dataStack;
char c;
vector<Tocken>::iterator tmpite = WordArray.begin();
while (tmpite != WordArray.end() || operStack.size() != 0)
{
if (tmpite != WordArray.end() && tmpite->second == 5)//是运算数字,则进操作数的栈
{
p = new Node;
p->oper = tmpite->first;
p->left = NULL;
p->right = NULL;
dataStack.push(p);
tmpite++;
}
else
{
if (tmpite != WordArray.end()){
switch (tmpite->first[0])
{
case '('://进栈
operStack.push('(');
tmpite++;
break;
case ')'://脱括号
while (true)
{
c = operStack.top();
operStack.pop();
if (c == '(')
{
break;
}
p = new Node;
p->oper = c;
p->left = NULL;
p->right = NULL;
if (dataStack.size())
{
p->right = dataStack.top();
dataStack.pop();
}
if (dataStack.size())
{
p->left = dataStack.top();
dataStack.pop();
}
dataStack.push(p);
}
tmpite++;
break;
default:
if (operStack.size() == 0 || getOperPri(operStack.top()) < getOperPri(tmpite->first[0]))
{//进栈
operStack.push(tmpite->first[0]);
tmpite++;
}
else
{//出栈
p = new Node();
p->oper = operStack.top();
p->left = NULL;
p->right = NULL;
if (dataStack.size())
{
p->right = dataStack.top();
dataStack.pop();
}
if (dataStack.size())
{
p->left = dataStack.top();
dataStack.pop();
}
dataStack.push(p);
operStack.pop();
}
break;
}
}
else{
p = new Node();
p->oper = operStack.top();
p->left = NULL;
p->right = NULL;
if (dataStack.size())
{
p->right = dataStack.top();
dataStack.pop();
}
if (dataStack.size())
{
p->left = dataStack.top();
dataStack.pop();
}
dataStack.push(p);
operStack.pop();
}
}
}
p = dataStack.top();
dataStack.pop();
}
void PutIn(string& expr)
{
cout << "输入转化的表达式\n";
cin >> expr;
}
bool AfterTraversal(Node* p, vector<string>& After)
{
if (NULL == p){
return false;
}
AfterTraversal(p->left, After);
AfterTraversal(p->right, After);
cout << p->oper << " ";
After.push_back(p->oper);
return true;
}
/*--------------------------------词法分析----------------------------*/
bool word_analysis(vector<Tocken>& word, const string expr)
{
for (int i = 0; i<expr.length(); ++i)
{
// 如果是 + - * / ( )
if (expr[i] == '(' || expr[i] == ')' || expr[i] == '+'
|| expr[i] == '-' || expr[i] == '*' || expr[i] == '/')
{
string tmp;
tmp.push_back(expr[i]);
switch (expr[i])
{
case '+':
word.push_back(make_pair(tmp, Add));
break;
case '-':
word.push_back(make_pair(tmp, Sub));
break;
case '*':
word.push_back(make_pair(tmp, Mul));
break;
case '/':
word.push_back(make_pair(tmp, Div));
break;
case '(':
word.push_back(make_pair(tmp, LetfBra));
break;
case ')':
word.push_back(make_pair(tmp, RightBra));
break;
}
}
// 如果是数字开头
else if (expr[i] >= '1' && expr[i] <= '9')
{
string tmp;
while (expr[i] >= '0' && expr[i] <= '9')
{
tmp.push_back(expr[i]);
++i;
}
word.push_back(make_pair(tmp, Num));
--i;
}
else
{
return false;
}
}
return true;
}
/*--------------------------------语法分析----------------------------*/
// 读下一单词的种别编码
void Next()
{
if (idx < word.size())
sym = word[idx++].second;
else
sym = Other;
}
// E → TE'
void E()
{
T();
E1();
}
// E' → +TE' | -TE' | ε
void E1()
{
if (sym == 1)
{
Next();
T();
E1();
}
else if (sym == 2)
{
Next();
T();
E1();
}
else if (sym != 7 && sym != 0)
{
err = -1;
}
}
// T → FT'
void T()
{
F();
T1();
}
// T' → *FT' | /FT' | ε
void T1()
{
if (sym == 3)
{
Next();
F();
T1();
}
else if (sym == 4)
{
Next();
F();
T1();
}
else if (sym != 1 && sym != 2 && sym != 7 && sym != 0)
{
err = -1;
}
}
// F → (E) | d
void F()
{
if (sym == 5)
{
Next();
}
else if (sym == 6)
{
Next();
E();
if (sym == 7)
{
Next();
}
else
{
err = -1;
}
}
else
{
err = -1;
}
}
int prior(char c)
{
switch (c)
{
case '+':
case '-':
return 1;
case '*':
case '/':
return 2;
default:
return 0;
}
}
bool isOperator(char c)
{
switch (c)
{
case '+':
case '-':
case '*':
case '/':
return true;
default:
return false;
}
}
// 从栈中连续弹出两个操作数
void popTwoNumbers(stack<int>& s, int& first, int& second)
{
first = s.top();
s.pop();
second = s.top();
s.pop();
}
// 计算后缀表达式的值
int expCalculate(const vector<string>& postfix)
{
int first, second;
stack<int> s;
for (int i = 0; i<postfix.size(); ++i)
{
string c = postfix[i];
switch (c[0])
{
case '+':
popTwoNumbers(s, first, second);
s.push(second + first);
break;
case '-':
popTwoNumbers(s, first, second);
s.push(second - first);
break;
case '*':
popTwoNumbers(s, first, second);
s.push(second*first);
break;
case '/':
popTwoNumbers(s, first, second);
s.push(second / first);
break;
default:
s.push(atoi(c.c_str()));
break;
}
}
int result = s.top();
s.pop();
return result;
}
int main()
{
string expr;
PutIn(expr);
vector<string> After;
Node* p = new Node();
if (!word_analysis(word, expr)){
cout << "输入一个错误的表达式" << endl;
}
else
{
Next();
E();
if (sym == 0 && err == 0){ // 注意要判断两个条件
cout << "表达式正确" << endl;
generateTree(p,word);
AfterTraversal(p, After);
cout << endl;
cout << "值为:"<< expCalculate(After);
}
else
cout << "输入错误的表达式" << endl;
}
return 0;
}
原代码(ps.因为是按模块组合写的,可能有一些函数会有重复,大家看的时候见谅)