用栈实现中缀表达式转后缀表达式以及后缀表达式的计算

引言

  任何一个表达式都是由操作数、运算符、界限符组成的。这里讨论简单的加、减、乘、除四种运算符。我们在此把运算符和界限符统称运算符,将它们构成的集合命名为OP。

  根据加减乘除的运算规则,在每一步运算中,设先出现的操作符为c1,在这个操作符之后出现的那一个字符为c2,下表定义了两个操作符之间的优先关系。(>表示c1优先权高于c2,=表示c1优先权等于c2,<表示c1的优先权小于c2。)

               运算符间的优先关系(c1为左侧,c2为上侧)

c1 ,c2 + - * / ( ) #
+ > > < < < > >
- > > < < < > >
* > > > > < > >
/ > > > > < > >
( < < < < < =
) > > > > > >
# < < < < < =


用栈将中缀表达式转化成后缀表达式

  为了将中缀表达式转化成后缀表达式,我们需要先设立一个OPTR工作栈来寄存运算符,初始化为空栈;用一个字符串s来寄存现有的转化一部分的表达式,初始化为空串。读入的表达式的末尾用’#‘表示。

  具体步骤:

1.初始化OPTR为空栈,并将字符‘#’存入栈中作为栈底元素。

2.读入第一个字符ch,如果没有读到表达式的末尾’#‘或OPTR的栈顶元素不为’#‘时,则循环执行以下操作:

(1)ch若是操作数,则直接加入s,读取下一个ch。

(2)ch若是运算符,则比较OPTR的栈顶元素和ch的优先性,进行如下操作:

a.若是栈顶元素的优先性小于ch,则将ch压入OPTR栈,读取下一个ch。

b.若是栈顶元素的优先性大于ch,则弹出OPTR的栈顶元素,并将其加入字符串s。

c.若等于,则OPTR的栈顶元素是‘(’并且读入的ch是‘)’,这时相当于括号匹配成功,应直接弹出OPTR的栈顶元素‘(’,然后继续读入下一元素ch。

3.循环完成后,s即为转化后的后缀表达式。

以下为中缀表达式a/b+(c*d-e*f)/g转化成后缀表达式的表格:

步骤 OPTR栈 字符串s 读入字符 主要操作
1 # a/b+(c*d-e*f)/g# 'a'加入s
2 # a /b+(c*d-e*f)/g# push(OPTR,'/')
3 #/ a b+(c*d-e*f)/g# 'b'加入s
4 #/ ab +(c*d-e*f)/g# pop(OPTR,'/'),/加入s
5 # ab/ +(c*d-e*f)/g# push(OPTR,'+')
6 #+ ab/ (c*d-e*f)/g# push(OPTR,'(')
7 #+( ab/ c*d-e*f)/g# 'c'加入s
8 #+( ab/c *d-e*f)/g# push(OPTR,'*')
9

#+(*

ab/c d-e*f)/g# 'd'加入s
10 #+(* ab/cd -e*f)/g# pop(OPTR,'*'),*加入s
11 #+( ab/cd* -e*f)/g# push(OPTR,'-')
12 #+(- ab/cd* e*f)/g# 'e'加入s
13 #+(- ab/cd*e *f)/g# push(OPTR,'*')
14 #+(-* ab/cd*e f)/g# 'f'加入s
15 #+(-* ab/cd*ef )/g# pop(OPTR,'*'),*加入s
16 #+(- ab/cd*ef* )/g# pop(OPTR,'-'),-加入s
17 #+( ab/cd*ef*- )/g# pop(OPTR,'(')
18 #+ ab/cd*ef*- /g# push(OPTR,'/')
19 #+/ ab/cd*ef*- g# 'g'加入s
20 #+/ ab/cd*ef*-g # pop(OPTR,'/'),/加入s
21 #+ ab/cd*ef*-g/ # pop(OPTR,'+'),+加入s
22 # ab/cd*ef*-g/+ # return s

具体代码如下(使用c++):

sqstack的类如下:

#pragma once
#define __SQ_STACK_H__
// ANSI C++标准库头文件
#include 					// 标准串操作
#include 					// 标准流操作
using namespace std;
#define DEFAULT_SIZE 100
// 顺序栈模板类
template
class SqStack
{
protected:
	// 顺序栈的数据成员:
	int top;										// 栈顶指针 
	int maxSize;									// 栈的最大容量 
	ElemType* data;								// 元素存储空间
public:
	//  顺序栈的方法声明及重载编译系统默认方法声明:
	SqStack(int size = DEFAULT_SIZE);				// 构造函数
	virtual ~SqStack();							// 析构函数
	int getLength() const;							// 求栈的长度			 
	bool isEmpty() const;							// 判断栈是否为空
	void clear();									// 将栈清空
	void traverse(void (*Visit)(const ElemType&)) const;	// 遍历栈
	int push(const ElemType e);				    // 入栈
	int getTop(ElemType& e) const;				    // 取顶元素
	int pop(ElemType& e);					    // 出栈
	SqStack(const SqStack& s);		// 复制构造函数
	SqStack& operator =(const SqStack& s); // 赋值语句重载
	int gettop() { return top; }
};
template
SqStack::SqStack(int size) {
	top = -1;       //栈顶指针初始化为-1
	maxSize = size;
	data = new ElemType[size];
}

template
int SqStack::getLength() const {
	return top + 1;
}

template
bool SqStack::isEmpty() const {
	if (top == -1) return true;
	else return false;
}

template
void SqStack::clear() {
	delete data;
	data = NULL;
	top = -1;
}

template
void SqStack::traverse(void (*Visit)(const ElemType&)) const {   //遍历
	for (int i = 0; i <= top; i++) {
		Visit(data[i]);       //遍历表中每一个元素
	}
}

template
int SqStack::getTop(ElemType& e) const {
	if (top == -1) {
		cout << "此栈为空,无法取栈顶元素!" << endl;
		return 0;
	}
	else {
		e = data[top];      //取栈顶元素
		return 1;
	}
}

template
int SqStack::push(const ElemType e) {
	if (top == maxSize - 1) {
		cout << "栈已满,无法入栈!" << endl;
		return 0;
	}
	else {
		top++;
		data[top] = e;
	}
}

template
int SqStack::pop(ElemType& e) {
	if (top == -1) {
		cout << "此栈为空,无法出栈!" << endl;
		return 0;
	}
	else {
		e = data[top];
		top--;
		return 1;
	}
}

template
SqStack::SqStack(const SqStack& s) {
	maxSize = s.maxSize;
	top = s.top;
	for (int i = 0; i <= s.top; i++) {
		data[i] = s.data[i];
	}
}

template
SqStack::~SqStack() { }

template
SqStack& SqStack::operator=(const SqStack& s) {
	maxSize = s.maxSize;
	top = s.top;
	for (int i = 0; i <= s.top; i++) {
		data[i] = s.data[i];
	}
}

转化的函数:

#include 
#include "sqstack.h""
#define DEFAULT_SIZE 100
using namespace std;
char precede(char c1, char c2);
void conversion();
void calculate();
char precede(char c1, char c2) {         //比较c1和c2的优先性,返回‘<',‘>'或‘=’。
	switch (c1) {
	case '+':if (c2 == '+' || c2 == '-' || c2 == ')' || c2 == '#') return '>';
			else return'<';
		break;
	case '-':if (c2 == '+' || c2 == '-' || c2 == ')' || c2 == '#') return '>';
			else return'<';
		break;
	case '*':if (c2 == '(') return '<';
			else return'>';
		break;
	case '/':if (c2 == '(') return '<';
			else return'>';
		break;
	case '(':if (c2 == ')') return '=';
			else if (c2 != '#') return'<';
		break;
	case ')':if (c2 != '(') return '>';
		break;
	case '#':if (c2 != ')' && c2 != '#') return '<';
			else if (c2 == '#') return'=';
		break;
	}
}
void conversion() {         //将中缀表达式转化成后缀表达式
	SqStack OPTR;       //先初始化一个字符栈
	OPTR.push('#');
	cout << "请输入一个中缀表达式:";
	char c[100];
	int k = 0;
	while (k < 100 && (c[k] = getchar()) != '=') {      //输入表达式
		k++;
	}
	c[k] = '#';
	c[k+1] = '\0';
	int i = 0;         //用i来表示ch的位置
	char s[100];
	int j = 0;         //用j来表示s中下一步添加字符的位置
	char ch = c[i];       //初始化ch为表达式的第一个字符
	while (ch != '#' || OPTR.gettop() != 0) {
		if (ch != '+' && ch != '-' && ch != '*' && ch != '/' && ch != '(' && ch != ')' && ch != '#') {  //如果ch是操作数,直接加入s
			s[j] = ch;
			j++;
			ch = c[++i];
		}
		else {
			char e;
			OPTR.getTop(e);
			char pre = precede(e, ch);
			if (pre == '<') {
				OPTR.push(ch);
				ch = c[++i];

			}
			else if (pre == '>') {
				OPTR.pop(s[j]);
				j++;
			}
			else if (pre == '=') {
				char p;
				OPTR.pop(p);
				ch = c[++i];

			}
		}
	}
	s[j++] = '\0';
	printf("%s", s);
}

int main() {
	conversion();
	return 0;
}

运行截图如下:


用栈计算后缀表达式

  在计算后缀表达式的时候,可以设置一个int类型的栈,然后依次读取输入的表达式的每一个字符,如果遇到操作数,则直接将其转化为int类型然后进栈;如果遇到运算符,则从栈中取出两个数进行运算,再将运算结果入栈,代码如下。(sqstack同上):

void calculate() {
	cout << "请输入想计算的后缀表达式:";
	char s[100];
	cin >> s;
	SqStack stack;    //初始化一个栈
	int i = 0;
	while (s[i] != '\0') {
		if (s[i] != '+' && s[i] != '-' && s[i] != '*' && s[i] != '/') {    //如果是操作数,则进栈
			int a = s[i] - '0';
			stack.push(a);
		}
		else {                     //如果是操作符,则取出栈顶两个元素进行计算,并将结果入栈
			int b, a;
			stack.pop(b);
			stack.pop(a); 
			if (s[i] == '+') stack.push(a + b);
			else if (s[i] == '-') stack.push(a - b);
			else if (s[i] == '*') stack.push(a * b);
			else stack.push(a / b);
		}
		i++;
	}
	int a;
	stack.getTop(a);
	cout << "计算结果为:" << a << endl;
}

运行截图如下:

你可能感兴趣的:(数据结构)