数据结构 C++实现 算术表达式求值

一、实验目的

1、了解栈的特性,以及它在实际问题中的应用。
2、掌握栈的实现方法以及它的基本操作,学会运用栈来解决问题。

二、实验要求

表达式求值是数学中的一个基本问题,也是程序设计中的一个经典问题。我们所涉及的表达式中包含数字(一位正整数)和运算符号,本课程设计中处理的运算符号包括‘+’、‘-’、‘’、‘/’、‘(’和‘)’。要求按照我们所习惯的计算顺序,正确计算出表达式的值,并输出至屏幕上。为了计算方便,表达式以#号开始,并以#号结束输入。例如表达式:#2(3+4)-6/3#,运行的输出结果为12。

三、代码内容

我是使用链栈实现的

1、创建链栈并初始化

#include<iostream>
#define OK 1
#define ERROR 0
using namespace std;
typedef char SElemType;
typedef int Status;
//链栈存储结构
typedef struct Node {
    
    
	SElemType data;
	struct Node* next;
}Node, * LinkStack;

//链栈初始化 
Status InitStack(LinkStack &S) {
    
    	//构造空栈,栈顶指针置空
	S = NULL;
	return OK;
}

2、入栈出栈取栈顶元素

//链栈入栈
Status Push(LinkStack &S, SElemType e) {
    
    //栈顶插入元素e
	LinkStack p = new Node;	//生成新节点
	p->data = e;	//新节点数据域置为e
	p->next = S;	//将新节点插入栈顶
	S = p;	//修改栈顶指针为p
	return OK;
}

//链栈的出栈
Status Pop(LinkStack &S, SElemType &e) {
    
    
	if (S == NULL)	//栈为空
		return ERROR;
	LinkStack p;	//定义临时链栈
	e = S->data;	//将栈顶元素赋值给e
	p = S;	//临时存储栈顶空间,以备释放
	S = S->next;	//修改栈顶指针
	delete p;	//删除栈顶指针
	return OK;
}
//取栈顶元素
SElemType GetTop(LinkStack S) {
    
    
	if (S != NULL)	//栈非空
		return S->data;
}

3、判断是否是运算符

//判断读入的字符ch是否为运算符
Status In(SElemType ch) {
    
    
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')'||ch=='#')
		return OK;
	else
		return ERROR;
}

4、判断运算符优先级

//判断运算符栈顶元素与读入运算符ch的优先级
SElemType Precede(SElemType a, SElemType b) {
    
    
	if (a == '+' || a == '-') {
    
    
		if (b == '+' || b == '-' || b == '#' || b == ')')
			return '>';
		else 
			return '<';
	}
	if (a == '*' || a == '/') {
    
    
		if (b == '(')
			return '<';
		else 
			return '>';
	}
	if (a == '(') {
    
    
		if (b == ')')
			return '=';
		else 
			return '<';
	}
	if (a == '#') {
    
    
		if (b == '#')
			return '=';
		else 
			return '<';
	}
	if (a == ')')
		return '>';
}

5、运算函数

这里不需要将char转换为int来运算,只需要输出结果是转换一下即可

//运算函数
SElemType Operate(SElemType a, SElemType t, SElemType b) {
    
    //进行运算的函数 
	switch (t) {
    
    
	case '+':
		return a + b;
	case '-':
		return a - b;
	case '*':
		return a * b;
	case '/':
		return a / b;
	}
}

6、总代码

#include<iostream>
#define OK 1
#define ERROR 0
using namespace std;
typedef char SElemType;
typedef int Status;
//链栈存储结构
typedef struct Node {
    
    
	SElemType data;
	struct Node* next;
}Node, * LinkStack;

//链栈初始化 
Status InitStack(LinkStack &S) {
    
    	//构造空栈,栈顶指针置空
	S = NULL;
	return OK;
}

//链栈入栈
Status Push(LinkStack &S, SElemType e) {
    
    //栈顶插入元素e
	LinkStack p = new Node;	//生成新节点
	p->data = e;	//新节点数据域置为e
	p->next = S;	//将新节点插入栈顶
	S = p;	//修改栈顶指针为p
	return OK;
}

//链栈的出栈
Status Pop(LinkStack &S, SElemType &e) {
    
    
	if (S == NULL)	//栈为空
		return ERROR;
	LinkStack p;	//定义临时链栈
	e = S->data;	//将栈顶元素赋值给e
	p = S;	//临时存储栈顶空间,以备释放
	S = S->next;	//修改栈顶指针
	delete p;	//删除栈顶指针
	return OK;
}

//取栈顶元素
SElemType GetTop(LinkStack S) {
    
    
	if (S != NULL)	//栈非空
		return S->data;
}

//判断读入的字符ch是否为运算符
Status In(SElemType ch) {
    
    
	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '(' || ch == ')'||ch=='#')
		return OK;
	else
		return ERROR;
}

//判断运算符栈顶元素与读入运算符ch的优先级
SElemType Precede(SElemType a, SElemType b) {
    
    
	if (a == '+' || a == '-') {
    
    
		if (b == '+' || b == '-' || b == '#' || b == ')')
			return '>';
		else 
			return '<';
	}
	if (a == '*' || a == '/') {
    
    
		if (b == '(')
			return '<';
		else 
			return '>';
	}
	if (a == '(') {
    
    
		if (b == ')')
			return '=';
		else 
			return '<';
	}
	if (a == '#') {
    
    
		if (b == '#')
			return '=';
		else 
			return '<';
	}
	if (a == ')')
		return '>';
}

//运算函数
SElemType Operate(SElemType a, SElemType t, SElemType b) {
    
    //进行运算的函数 
	switch (t) {
    
    
	case '+':
		return a + b;
	case '-':
		return a - b;
	case '*':
		return a * b;
	case '/':
		return a / b;
	}
}

//算法表达式求值的优先算法,设OPTR和OPND分别为运算符栈和操作数栈
void EvaluateExpression() {
    
    
	LinkStack OPND, OPTR;	//定义栈
	SElemType ch, t,t1,t2;
	InitStack(OPND);	//初始化操作数栈
	InitStack(OPTR);	//初始化运算符栈
	Push(OPTR,'#');	//入栈
	cin >> ch;
	while (ch != '#' || GetTop(OPTR) != '#') {
    
    //表达式没有扫描完毕或者OPTR栈顶不为‘#’时执行
		if (!In(ch)) {
    
    	//ch不是运算符
			Push(OPND, ch-'0');	//进入OPND栈
			cin >> ch;	//读取下一个字符
		}
		else
			switch (Precede(GetTop(OPTR), ch)) {
    
    	//比较OPTR栈顶元素和ch的优先级
			case '<':
				Push(OPTR, ch);	//将ch压入OPTR栈
				cin >> ch;	//读取下一个字符
				break;
			case '>':
				Pop(OPTR, t);	//弹出OPTR栈顶运算符,赋值给t
				Pop(OPND, t2);	//后进先出
				Pop(OPND, t1);	//弹出OPND栈顶两个运算数
				Push(OPND, Operate(t1, t, t2));	//将运算结果压入OPND栈
				break;
			case '=':	//OPTR栈顶元素是'('且ch是')'
				Pop(OPTR, t);	//弹出栈顶'('
				cin >> ch;	//读取下一个字符
				break;
			}
	}
	cout<<(int)GetTop(OPND)<<endl;	//将char转换为int
}

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

四、运算结果

#2*(3+4)-6/3#
在这里插入图片描述
第一个#已经入栈过了

五、总结

这里使用链栈来实现,也可以使用顺序栈来实现
程序整体比较简单,健壮性不高,界面简单,没有提示语句

猜你喜欢

转载自blog.csdn.net/qq_54388490/article/details/123742067