终于等到你

众里寻他千百度,蓦然回首,那人却在灯火阑珊处。

表达式的后缀表示

表达式的后缀表示

基本要求

  • 设计一转换程序,将输入的任一表达式转换成相应的后缀形式后输出。
  • 为简单起见,假定运算对象只含变量,且每个变量名以单字母表示;运算符仅含+、-、*、/和圆括号;表达式以分号“;”结尾。在转换过程中,要求作必要的语法检查,例如圆括号是否配对,单词是否合法等。
  • 分别编写转换程序的非递归与递归算法

用栈实现非递归算法。首先给出栈的类定义,建议用一个头文件保存

#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;
}

结束啦,欢迎大家指出错误之处

posted @ 2018-11-17 09:43  gzr2018  阅读(928)  评论(4编辑  收藏  举报