IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 表达式求值C++(栈、加减乘除幂运算、一位小数、一为整数) -> 正文阅读

[数据结构与算法]表达式求值C++(栈、加减乘除幂运算、一位小数、一为整数)

输入输出示例
在这里插入图片描述

自定义的线性表数据结构

这是数据成员变量和部分需要用到的成员函数
1.有参构造函数new一个给定长度与类型的线性表
2.append函数将传入的值添加到线性表末尾
3.getValue返回给定下标索引的值
4.getLength返回当前线性表长度

template<class T>
class arrList {
private:
	int maxSize;
	T* data;
	int curlen;

public:
	arrList(int mSize) {
		maxSize = mSize;
		data = new T[maxSize];
		curlen = 0;
	}
	~arrList() {
		curlen = 0;
	}

	bool append(const T x) {
		if (curlen >= maxSize) {
			printf("表已满\n");
			return false;
		}
		data[curlen++] = x;
		return true;
	}
	T getValue(const int pos) {
		if (pos<0 || pos>curlen - 1) {
			printf("wrong position");
			exit(0);
			return NULL;
		}
		return data[pos];
	}
	int getLength() {
		return curlen;
	}

};

中缀表达式转后缀表达式

从头到尾依次扫描中缀序列mid。
1.如果为操作数,则直接输出到post序列
ps:这里需要注意数符转换的问题,因为mid中是char型数据,所以计算机按ASCII码存储。如果直接输出到post序列中计算,则是二者ASCII的值相计算,2+3实际算的是’2’+‘3’。所以这里转换一下,将每个数字字符减48,这样得到的ASCII值在读取时才能表示为真正要参与运算的值。

2.如果为开括号,则将开括号入栈。
3.如果为闭括号,则将此时栈中开括号之前的元素全部弹出到post序列
4.如果为运算符,要决定是pop弹栈还是push入栈
(1)如果栈为空,则没得弹,只能入栈
(2)如果栈顶为开括号,因为开括号要保留,所以不弹,将运算符入栈
(3)如果栈顶为运算符且运算符优先级低,则不弹,将运算符入栈
ps:在后缀表达式中,运算符靠前的先算,所以先入post的是高优先级运算符。这里如果输入运算符优先级高,也不能直接入post,因为后边的运算符优先级可能更高,或者有括号的情况,所以这里先用栈记录下来,好跟后边的比。
(4)上述三项均不满足则将栈中元素用while一直往外弹到post序列中,直到三个条件满足之一。

template<class T>
bool midToPost(arrList<char> mid, arrList<T> &post) {
	stack<T> stk;
	for (int i = 0; i < mid.getLength(); i++) {
		T c = mid.getValue(i);
		//printf("%c  ", c);
		if (c <= '9' && c >= '0')//遇到操作数
			post.append(c - 48);
		else if (c == '(')//遇到开括号
			stk.push(c);

		else if (c == ')') {//遇到闭括号
			if (stk.empty()) {
				printf("中缀表达式错误");
				return false;
			}
			while (stk.top() != '(') {//将开括号之前都出栈
				post.append(stk.top());
				stk.pop();
			}
			stk.pop();//弹出开括号
		}//else if
		else {//遇到操作符
			while (!stk.empty() && stk.top() != '(' && isPrior(stk.top(), c)) {
				post.append(stk.top());
				stk.pop();
			}
			stk.push(c);
		}//else
		
	}//for
	while (!stk.empty()) {
		post.append(stk.top());
		stk.pop();
	}
	post.append('=');//后缀表达式结束标志
	//printArr<char>(post);
	return true;
}

比较运算符优先级

这个函数用于比较栈顶(第一个传参)和中缀表达式扫描到的要处理的运算符(第二个传参)优先级,如果top优先级高则返回true,否则返回false。
(这里小数点也当作运算符处理,a.b运算规则:a+0.1*b)
运算符优先级如下所示
小数点、幂运算>乘除>加减
1. 按运算符优先级检查top,如果top为最高优先级,则c优先级一定不高于top。
2. 如果top为中等优先级,则分类讨论。如果c为最高优先级,则返回false,其他返回true。
3. 如果top为最低优先级,则同样分类讨论。如果c为中等or最高优先级,则返回false,其他返回true。

template<class T>
bool isPrior(T top,char c) {
	if (top == '.' || top == '^')
		return true;
	else if (top == '*' || top == '/') {
		if (c == '.' || c == '^')
			return false;
		else
			return true;
	}
	else {
		if (c == '*' || c == '/' || c == '.' || c == '^')
			return false;
		else
			return true;
	}
}

后缀表达式计算

从头读取post序列。
1.遇到操作数入栈。
2.遇到运算符则从栈顶取出两个元素,与运算符计算,将计算结果压回栈中。

template<class T>
bool calPost(arrList<T> post) {
	stack<double> res;
	for(int i=0;post.getValue(i)!='=';i++) {
		char pointer = post.getValue(i);
		if (pointer < 10 && pointer >= 0) {
			res.push(pointer);
		}
		
		else {
			double a = res.top(); res.pop();
			double b = res.top(); res.pop();
			printf("%lf %c %lf = ", b,pointer, a);
			switch (pointer) {
				case('+'):res.push(b + a); break;
				case('-'):res.push(b - a); break;
				case('*'):res.push(b * a); break;
				case('/'):res.push(b / a); break;
				case('^'):res.push(exp(b, a)); break;
				case('.'):res.push(point(b, a)); break;
				default:break;
			}
			printf("%lf\n", res.top());
		}
		
	}//for
	printf("result= %lf",double(res.top()));
	return true;
}

输出

如果要输出的是数字,则将ASCII值+48输出对应的数字。
如果要输出的符号,则直接输出。

template<class T>
void printArr(arrList<T> arr) {
	for (int i = 0; i < arr.getLength(); i++) {
		if (arr.getValue(i) < 9 && arr.getValue(i) > 0)
			printf("%c", arr.getValue(i)+48);
		else
			printf("%c", arr.getValue(i));
	}
	printf("\n");
}

主程序

int main() {
	char c = '0';
	arrList<char> mid_input = arrList<char>(20);
	printf("please input mid_representation:\n");
	while (1) {
		scanf("%c", &c);
		if (c == '='||c=='\n')
			break;
		mid_input.append(c);
	}
	printf("中缀表达式:"); printArr<char>(mid_input);
	arrList<char> post = arrList<char>(20);
	midToPost<char>(mid_input, post);
	printf("后缀表达式:"); printArr<char>(post);
	calPost<char>(post);
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:50:35  更:2022-03-30 18:53:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:59:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码