表达式的后缀表示
表达式的后缀表示
基本要求
- 设计一转换程序,将输入的任一表达式转换成相应的后缀形式后输出。
- 为简单起见,假定运算对象只含变量,且每个变量名以单字母表示;运算符仅含+、-、*、/和圆括号;表达式以分号“;”结尾。在转换过程中,要求作必要的语法检查,例如圆括号是否配对,单词是否合法等。
- 分别编写转换程序的非递归与递归算法
用栈实现非递归算法。首先给出栈的类定义,建议用一个头文件保存
#include<iostream>
#include<assert.h>
using namespace std;
const int stackIncreament = 20;//溢出时的扩容
template<class T>
class SeqStack
{
public:
T * elements;
int top;
int maxSize;
void overflowProcess();
public:
SeqStack(int sz =50);
~SeqStack(){ delete[]elements; }
void Push( const T& x);
bool Pop(T& x);
bool Top(T& x);
bool IsEmpty()const { return(top == -1) ? true : false; }
bool IsFull()const { return (top == maxSize - 1) ? true : false; }
int getSize()const { return top + 1; };
void MakeEmpty() { top = -1; }
friend ostream&operator<<(ostream& os, SeqStack<T>&s);
};
template <class T>
SeqStack<T>::SeqStack(int sz) :top(-1), maxSize(sz)
{
//建立最大尺度为sz的空栈
elements = new T[maxSize];//创建数组
assert(elements != NULL);//断言:动态分配内存成功与否
}
template<class T>
void SeqStack<T>::overflowProcess()
{
T* newArray = new T[maxSize + stackIncreament];
if (newArray == NULL) { cerr << " new error!" << endl; exit(1); }
for (int i = 0; i <= top; i++)newArray[i] = elements[i];
maxSize = maxSize + stackIncreament;
delete[]elements;
elements = newArray;
}
template<class T>
void SeqStack<T>::Push(const T&x)
{
if(IsFull()==true) overflowProcess();
elements[++top] = x;
}
template<class T>
bool SeqStack<T>::Pop(T &x)
{
if (IsEmpty() == true)return false;
x = elements[top--];
return true;
}
template <class T>
bool SeqStack<T>::Top(T&x)
{
if (IsEmpty())return false;
x = elements[top];
return true;
}
语法检查函数,优先级预处理,都可以视为pre-operation
bool check_op(char a)
{
if (a == '*' || a == '/' || a == '+' || a == '-' || a == '%')return true;
return false;
}
map<char, int>isp; map<char, int>icp;
void Init()
{
isp['#'] = 0; isp['('] = 1; isp['*'] = 5; isp['/'] = 5; isp['%'] = 5; isp['+'] = 3; isp[')'] = 6; isp['-'] = 3;
icp['#'] = 0; icp['('] = 6; icp['*'] = 4; icp['/'] = 4; icp['%'] = 4; icp['+'] = 2; icp[')'] = 1; icp['-'] = 2;
}
bool pre_check(string expression)//语法检查
{
int numl = 0, numr = 0;
//最前面为操作符或者最后面为操作符,因为要求表达式以';'结尾,检查倒数第二个
if (check_op(expression[0]) || check_op(expression[expression.size() - 2]))
{
cout << "表达式格式错误,please check!" << endl;
return false;
}
for (int i = 0; i < expression.size()-1; i++)
{
//连续的操作数
if (isalpha(expression[i]) && isalpha(expression[i + 1])) {
cout << "表达式格式错误,please check!" << endl;
return false;
}
//连续的操作符
if (check_op(expression[i]) && check_op(expression[i + 1])) {
cout << "表达式格式错误,please check!" << endl;
return false;
}
//左右括号是否匹配
if (expression[i] == '(')numl++;
if (expression[i] == ')')numr++;
//首先出现左括号
if (numl < numr)
{
cout << "表达式格式错误,please check!" << endl;
return false;
}
}
if (numl != numr) {
cout << "表达式格式错误,please check!" << endl;
return false;
}
return true;
}
非递归算法,数据结构stack实现
void inffix_suffix(string expression)
{
if (!pre_check(expression))return;
//string sss = ";";
Init();
int i = 0;
SeqStack<char>s;
char ch = '#', ch1, op;
s.Push(ch); ch = expression[i++];
while (!s.IsEmpty() && ch != '#')
{
if (isalpha(ch)) { cout << ch; ch = expression[i++]; }//操作数直接输出
else
{
s.Top(ch1);//栈顶元素ch1
if (isp[ch1] < icp[ch]) { s.Push(ch); ch = expression[i++]; }//新输入的操作符优先级高,进栈
else if (isp[ch1] > icp[ch]) { s.Pop(op); cout << op; }//优先级低,退栈
else {
s.Pop(op);//优先级相同,先左后右
if (op == '(')ch = expression[i++];//此时说明,栈内的是'(',栈外的是')',ch = expression[i++]表示直接到')'的后一个
}
}
}
cout << endl;
}
递归写法
//此处没有再次进行语法检查,没有调用pre_check(expression))和Init();因为在main函数中,非递归先调用,以及调用前面两个函数
void inffix_suffix(string expression)
{
if (!pre_check(expression))return;
//string sss = ";";
Init();
int i = 0;
SeqStack<char>s;
char ch = '#', ch1, op;
s.Push(ch); ch = expression[i++];
while (!s.IsEmpty() && ch != '#')
{
if (isalpha(ch)) { cout << ch; ch = expression[i++]; }//操作数直接输出
else
{
s.Top(ch1);//栈顶元素ch1
if (isp[ch1] < icp[ch]) { s.Push(ch); ch = expression[i++]; }//新输入的操作符优先级高,进栈
else if (isp[ch1] > icp[ch]) { s.Pop(op); cout << op; }//优先级低,退栈
else {
s.Pop(op);//优先级相同,先左后右
if (op == '(')ch = expression[i++];//此时说明,栈内的是'(',栈外的是')',ch = expression[i++]表示直接到')'的后一个
}
}
}
cout << endl;
}
结束啦,欢迎大家指出错误之处
不疯魔不成活