【数据结构】表达式的后缀表示

一、实验题目及要求

题目:表达式的后缀表示

表达式中包含运算对象、运算符和圆括号等,习惯上使用中缀表示(指运算符夹在两运算符对象中间)形式。计算表达式的值,涉及到运算符的优先级别,如先乘除后加减。括在一对圆括号中的子表达式必须先计算,因此,圆括号可视为特殊的运算符,具有最高优先级别。圆括号可以任意嵌套,这意味着左圆括号后面又是表达式,形成表达式的递归定义。为了直接指明表达式中各运算对象的先后计算顺序,可将表达式的中缀形式转换成后缀(指运算符放在二运算对象的后面)形式。例如,表达式a*b-(c+d)/e,这是通常的中缀形式,其后缀表示是ab*cd+e/-,其中圆括号在后缀形式中已不见了。

     设计一转换程序,将输入的任一表达式转换成相应的后缀形式后输出。

二、需求分析

在转换过程中,要求作必要的语法检查,例如圆括号是否配对,单词是否合法等。

三、概要设计

考虑用栈实现。

1、用string类型的对象存储输入的中缀表达式;

2、从0位置开始判断字符,如果是数字,那就要判断后面是否是数字,如果是就不断扫描组成一个整数,最终组成一个整数,然后输出这个数;

3、如果是左括号,直接进栈;

4、如果是操作运算符,与栈顶元素比较优先级,如果高就压入栈;如果低,就取出栈顶元素输出;接着,栈顶元素和当前运算符号继续比较优先级,重复前面步骤,直到栈空或者当前的符号优先级高;

5、如果是右括号,把栈顶的元素取出,如果不是左括号,把取出的运算符输出,接着取栈顶的元素,直到栈中取出的符号是左括号;

6、扫描完成后,判断栈是否为空,若不为空,把符栈顶的元素取出并输出,直到栈空为止。

四、测试结果

4a24a9a5a16f4e9886853e381bcb964d.png

五、源代码

stack.h

#ifndef STACK_H_
#define STACK_H_
#include <iostream>
using namespace std;

template<class T>
class stack {
public:
	stack();
	~stack();
	void push(T t);//压栈
	T top();//取栈顶元素
	T pop();//出栈
	int size();//大小
	int isEmpty();//判断栈是否为空
private:
	T* arr;
	int count;
};

//构造
template<class T>
stack<T>::stack() 
{ 
	arr = new T[100];
	if (!arr) 
	{cout << "出错" << endl;}
}

//析构
template<class T>
stack<T>::~stack() {
	if (arr) {
		delete[] arr;
		arr = NULL;
	}
}

//向栈中添加一个元素
template<class T>
void stack<T>::push(T t) 
{arr[count++] = t;}

//取栈顶元素
template<class T>
T stack<T>::top() 
{return arr[count - 1];}

// 返回栈顶元素并删除
template<class T>
T stack<T>::pop() 
{
	int ret = arr[count - 1];
	count--;
	return ret;
}

// 返回栈的大小
template<class T>
int stack<T>::size()
{
	return count;
}

//判断栈是否为空
template<class T>
int stack<T>::isEmpty() {
	return size() == 0;
}


#endif

ReversePolish.cpp

//求逆波兰表达式(非递归版本)
#include <iostream>
#include<string>
#include"stack.h"
using namespace std;

// 判断是否是操作符
int isOperator(char ch) {
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/')
		return 0;
	if (ch == '(' || ch == ')')
	    return 1;
	return 2;
}


//获取优先级
int priority(char ch) {
	int level = 0; //优先级

	switch (ch) {
	case '(':
		level = 1;
		break;
	case '+':
	case '-':
		level = 2;
		break;
	case '*':
	case '/':
		level = 3;
		break;
	default:
		break;
	}
	return level;
}

bool Rational(string str)//判断输入的表达式的合理性
{
	int temp = 0;
	if (str[0] == '/' || str[0] == '*' || str[0] == '+' || str[0] == '-')//以运算符开头
		return false;
	for (int i = 0; i < str.length(); i++)
	{
		if (i < str.length() - 1)
		{
			if (isOperator(str[i])==0&&isOperator(str[i + 1])==0) return false;
		}
		if (i < str.length() - 1)
		{
			if (str[i] == '(')//检查左右括号是否匹配
			{
				if (str[i + 1] == '*' || str[i + 1] == '/' || str[i + 1] == '-' || str[i + 1] == '+')
					return false;//左括号后不能是运算符
				temp++;
			}
		}
		if (str[i] == ')')
		{
			if (i == 0)
				return false;
			if (str[i - 1] == '+' || str[i - 1] == '*' || str[i - 1] == '-' || str[i - 1] == '/')
				return false;//右括号前不能是运算符
			temp--;
		}
	}
	if (temp == 0)
		return true;
	else
		return false;
}



int main() 
{
	int num;
	string s;
	stack<char> op; // 栈op:存储操作符
	
	while(1) {
		cout << "请输入中缀表达式:" << endl;
		cin >> s;
		if (Rational(s) == false)
		{ 
			cout << "表达式不合理,请重新输入!" << endl; 
		    exit(0);
		}
		cout << "后缀表达式为:" << endl;
		int len, i;
		char c; // c存储从栈中取出的操作符
		len = (int)(s.length());
		i = 0;
		while (i < len) {
			if (isOperator(s[i])==2) {
				num = 0;
				do {
					cout << s[i];
					
					i++;
				} while (isdigit(s[i]));
				cout << " ";
			}
			else if (s[i] == '(') { // 左括号
				op.push(s[i]);
				i++;
			}
			else if (isOperator(s[i])==0) { //操作符
				if (op.isEmpty()) { //如果栈空,直接压入栈
					op.push(s[i]);
					i++;
				}
				else {
					// 比较栈op顶的操作符与ch的优先级
					// 如果ch的优先级高,则直接压入栈
					// 否则推出栈中的操作符,直到操作符小于ch的优先级,或者遇到(,或者栈已空
					while (!op.isEmpty()) {
						c = op.top();
						if (priority(s[i]) <= priority(c)) {
							// 优先级低或等于
							cout << c << " ";
							op.pop();
						}
						else // ch优先级高于栈中操作符
							break;
					} // while结束
					op.push(s[i]); // 防止不断的推出操作符,最后空栈了;或者ch优先级高了
					i++;
				} 
			}
			else if (s[i] == ')') { 
				// 如果是右括号,一直推出栈中操作符,直到遇到左括号(
				while (op.top() != '(') {
					cout << op.top() << " ";
					op.pop();
				}
				op.pop(); //把左括号推出栈
				i++;
			}
			else // 如果是空白符,就进行下一个字符的处理
				i++;
		}
		while (!op.isEmpty()) { // 当栈不空,继续输出操作符
			cout << op.top() <<" ";
			op.pop();
		}
		cout << std::endl;
	} 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_53700832/article/details/128903342