利用二叉树对表达式求值(只能处理个位的操作数)

news2024/11/27 8:23:10

题目:

题目要求: 用二叉树来表示表达式,树的每一个节点包括一个运算符和运算数。代数表达式中只包含+-*/和一位整数且没有错误。按照先括号,再乘除,后加减的规则构造二叉树。如图所示是"1+(2+3)*2-4/5"代数表达式对应二叉树,用对应的二叉树计算表达式的值。

输入格式:

输入一行表达式字符串,括号内只能有一个运算符。

输出格式:

输出表达式的计算结果.如果除数为0,提示divide 0 error!

https://images.ptausercontent.com/364

各个部分

二叉树节点:

typedef struct BiTNode{
	char date;
	BiTNode *left,*right;
	//构造函数 
	BiTNode()
	{date='#';left=right=NULL;}
	BiTNode(char dat)
	{ date=dat;left=right=NULL; }
	BiTNode(char dat,BiTNode *l,BiTNode *r)
	{ date=dat;left=l;right=r; }
}BiTNode,*ExpTree;

判断一个字符是不是运算符即最简单表达式的计算

//判断是否是运算符的函数 
bool judge(char c)
{
	if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#')
		return true;
	else return false;
}
int operate(int a,char c,int b)
{//不出现/0的情况 
    int ans;
	if(c=='+')
	    ans=a+b;
	else if(c=='-')
	    ans=a-b;
	else if(c=='*')
	    ans=a*b;
	else
	    ans=a/b;
	return ans;
}

构造表达式二叉树:

void InitExpTree(string s,ExpTree &T)
{
	stack<ExpTree> EXPT; //暂存二叉树 
	stack<char> OPTR;    //暂存运算符 
	OPTR.push('#');
	int i=0;   
	while(s[i]!='#'||OPTR.top()!='#')
	{
		if(s[i]>='0'&&s[i]<='9')
		{
			T=new BiTNode(s[i]);     //创建只有根节点的二叉树  
			EXPT.push(T);              //新树入栈
			i++;
		}
		else if(judge(s[i]))
		{
			switch(Precede(OPTR.top(),s[i]))  //栈顶元素优先级与当前元素优先级比较 
			{
				case '<':
				{	
					OPTR.push(s[i]);
					i++;
					break;
				}
				case '>':
				{
					char theta=OPTR.top();
					OPTR.pop();
					ExpTree b=EXPT.top();
					EXPT.pop();
					ExpTree a=EXPT.top();
					EXPT.pop();
					//theta为根,a为左子树,b为右子树,创建一颗二叉树; 
					T=new BiTNode(theta,a,b);
					//根节点T进EXPT栈
					EXPT.push(T);
					break;
				}
				case '=':    //()匹配的情况 
				{    
				    OPTR.pop();
				    i++;
					break; 
				}
			}//switch
		}
//		else if(s[i]==' ')
//		    i++;
//		i++;//case '>'时不用i++ 
	}//while
}

优先级比较函数:

//优先级比较函数 
char Precede(char e,char c)//e是栈顶元素,c是在读元素 
{
	int int_e,int_c;//将e和c转化为数字进行比较 
	map<char,int> optr;
	optr['+']=1;optr['-']=2;optr['*']=3;optr['/']=4;
	optr['(']=5;optr[')']=6;optr['#']=7;
	int_e=optr[e];
	int_c=optr[c];
	
	if(int_e==1||int_e==2)
	{
		if(int_c>=3&&int_c<=5) return'<';
		else return'>';
	}
	
	if(int_e==3||int_e==4)
	{
		if(int_c==5) return'<';
		else return '>';
	}
	
	if(int_e==5)
	{
		if(int_c==6) return '=';
		else if(int_c==7) return '#';
		else return '<';
	}
	
	if(int_e==6)
	{
		if(int_c==5) return '#';
		else return '>';
	}
	
	if(int_e==7)
	{
		if(int_c==7) return '=';
		else if(int_c==6) return '#';
		else return '<';
	}
}

根据二叉树来求值:

//根据二叉表达式来求值 
int EvaluateExpTree(ExpTree T)
{
	int lvalue=0,rvalue=0;
	if(T->left==NULL && T->right==NULL)
	    return T->date-'0';
	else
	{
		lvalue=EvaluateExpTree(T->left);
		rvalue=EvaluateExpTree(T->right);
		return operate(lvalue,T->date,rvalue);
	}
}

实现代码:

#include<iostream>
#include<vector>
#include<map>
#include<stack>
using namespace std;
typedef struct BiTNode{
	char date;
	BiTNode *left,*right;
	//构造函数 
	BiTNode()
	{date='#';left=right=NULL;}
	BiTNode(char dat)
	{ date=dat;left=right=NULL; }
	BiTNode(char dat,BiTNode *l,BiTNode *r)
	{ date=dat;left=l;right=r; }
}BiTNode,*ExpTree;
//判断是否是运算符的函数 
bool judge(char c)
{
	if (c == '+' || c == '-' || c == '*' || c == '/' || c == '(' || c == ')' || c == '#')
		return true;
	else return false;
}
int operate(int a,char c,int b)
{//不出现/0的情况 
    int ans;
	if(c=='+')
	    ans=a+b;
	else if(c=='-')
	    ans=a-b;
	else if(c=='*')
	    ans=a*b;
	else
	    ans=a/b;
	return ans;
}
//优先级比较函数 
char Precede(char e,char c)//e是栈顶元素,c是在读元素 
{
	int int_e,int_c;//将e和c转化为数字进行比较 
	map<char,int> optr;
	optr['+']=1;optr['-']=2;optr['*']=3;optr['/']=4;
	optr['(']=5;optr[')']=6;optr['#']=7;
	int_e=optr[e];
	int_c=optr[c];
	
	if(int_e==1||int_e==2)
	{
		if(int_c>=3&&int_c<=5) return'<';
		else return'>';
	}
	
	if(int_e==3||int_e==4)
	{
		if(int_c==5) return'<';
		else return '>';
	}
	
	if(int_e==5)
	{
		if(int_c==6) return '=';
		else if(int_c==7) return '#';
		else return '<';
	}
	
	if(int_e==6)
	{
		if(int_c==5) return '#';
		else return '>';
	}
	
	if(int_e==7)
	{
		if(int_c==7) return '=';
		else if(int_c==6) return '#';
		else return '<';
	}
}
void InitExpTree(string s,ExpTree &T)
{
	stack<ExpTree> EXPT; //暂存二叉树 
	stack<char> OPTR;    //暂存运算符 
	OPTR.push('#');
	int i=0;   
	while(s[i]!='#'||OPTR.top()!='#')
	{
		if(s[i]>='0'&&s[i]<='9')
		{
			T=new BiTNode(s[i]);     //创建只有根节点的二叉树  
			EXPT.push(T);              //新树入栈
			i++;
		}
		else if(judge(s[i]))
		{
			switch(Precede(OPTR.top(),s[i]))  //栈顶元素优先级与当前元素优先级比较 
			{
				case '<':
				{	
					OPTR.push(s[i]);
					i++;
					break;
				}
				case '>':
				{
					char theta=OPTR.top();
					OPTR.pop();
					ExpTree b=EXPT.top();
					EXPT.pop();
					ExpTree a=EXPT.top();
					EXPT.pop();
					//theta为根,a为左子树,b为右子树,创建一颗二叉树; 
					T=new BiTNode(theta,a,b);
					//根节点T进EXPT栈
					EXPT.push(T);
					break;
				}
				case '=':    //()匹配的情况 
				{    
				    OPTR.pop();
				    i++;
					break; 
				}
			}//switch
		}
//		else if(s[i]==' ')
//		    i++;
//		i++;//case '>'时不用i++ 
	}//while
}
//根据二叉表达式来求值 
int EvaluateExpTree(ExpTree T)
{
	int lvalue=0,rvalue=0;
	if(T->left==NULL && T->right==NULL)
	    return T->date-'0';
	else
	{
		lvalue=EvaluateExpTree(T->left);
		rvalue=EvaluateExpTree(T->right);
		return operate(lvalue,T->date,rvalue);
	}
}
int main()
{
	string s;
	cin>>s;
	ExpTree root;
	InitExpTree(s,root);
	int ans=EvaluateExpTree(root);
	cout<<"value:"<<ans;
}

 运行:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1146536.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

批量爬取指定多个网址的爱站权重关键词词库(爱站拓词自动去重)

批量爬取指定多个网址的爱站权重关键词词库软件介绍&#xff1a; 1、软件可以设置权重词的长度范围。 2、可设置权重词必须包含词。 3、可以设置爬取的页数。 4、可以设置爬取PC权重词、移动权重词。 5、可以放入多个网站&#xff0c;批量爬取多个网站的权重词。 6、爬取完…

Ubuntu更新中文包

设置 重启Ubuntu系统

灯光布置和场景模拟软件:Set A Light 3D Studio

Set A Light 3D Studio是一款专业的灯光模拟软件&#xff0c;旨在帮助摄影师和电影制片人在电脑上进行虚拟灯光布置和场景模拟&#xff0c;以实现更加精准和高质量的拍摄效果。该软件提供了丰富的灯光和场景模型&#xff0c;支持灵活调整光源位置、强度、颜色和效果等参数&…

IOC课程整理-20 Spring 应用上下文生命周期

0.目录 1. Spring 应用上下文启动准备阶段 2. BeanFactory 创建阶段 3. BeanFactory 准备阶段 4. BeanFactory 后置处理阶段 5. BeanFactory 注册 BeanPostProcessor 阶段 6. 初始化內建 Bean&#xff1a;MessageSource 7. 初始化內建 Bean&#xff1a;Spring 事件广播器…

Megatron-LM GPT 源码分析(四) Virtual Pipeline Parallel分析

引言 本文接着上一篇【Megatron-LM GPT 源码分析&#xff08;三&#xff09; Pipeline Parallel分析】&#xff0c;基于开源代码 GitHub - NVIDIA/Megatron-LM: Ongoing research training transformer models at scale &#xff0c;通过GPT的模型运行示例&#xff0c;从三个维…

sql-50练习题6-10

sql练习题6-10题 前言数据库表结构介绍学生表课程表成绩表教师表 0-6 查询"李"姓老师的数量0-7 查询学过"李四"老师授课的同学的信息0-8 查询没学过"李四"老师授课的同学的信息0-9 查询学过编号为"01"并且也学过编号为"02"的…

37回溯算法-理论基础

目录 什么是回溯算法 基本思想 问题场景 回溯算法的理解 回溯算法模板 LeetCode之路——257. 二叉树的所有路径 分析 什么是回溯算法 回溯算法是一种解决组合优化问题、搜索问题以及决策问题的算法。它通常用于尝试在一组可能的解决方案中搜索并找到满足特定条件的解。…

C++入门05—指针

1. 指针的基本概念 指针的作用&#xff1a; 可以通过指针间接访问内存 内存编号是从0开始记录的&#xff0c;一般用十六进制数字表示 可以利用指针变量保存地址 2. 指针变量的定义和使用 指针变量定义语法&#xff1a; 数据类型 * 变量名&#xff1b; 示例&#xff1a; …

如何防“AI换脸”诈骗

风险提示 “AI换脸”诈骗利用仿真技术冒充亲人、同事或公职人员声音相貌行骗&#xff0c;此类新型网络诈骗手段多样、门槛降低、辨别难度加大&#xff0c;常令公众放松警惕&#xff0c;短时间内造成较大损失。国家金融监督管理总局北京监管局近日发布风险提示&#xff1a;眼见…

震惊!原来BUG是这么理解的!什么是BUG?软件错误(BUG)的概念

较为官方的概念&#xff1a; 当且仅当规格说明是存在的并且正确&#xff0c;程序与规格说明之间的 不匹配才是错误。 当需求规格说明书没有提到的功能&#xff0c;判断标准以最终用户为准&#xff1a;当程序没有实现其最终用户合理预期的 功能要求时&#xff0c;就是软…

类EMD的“信号分解方法”及MATLAB实现(第八篇)——离散小波变换DWT(小波分解)

在之前的系列文章里&#xff0c;我们介绍了EEMD、CEEMD、CEEMDAN、VMD、ICEEMDAN、LMD、EWT&#xff0c;我们继续补完该系列。 今天要讲到的是小波分解&#xff0c;通常也就是指离散小波变换&#xff08;Discrete Wavelet Transform, DWT&#xff09;。在网上有一些介绍该方法…

AnyLogic 8.8.1---8.8.4 Crack,旧版不搞了

AnyLogic&#xff0c;是一款应用广泛的&#xff0c;对离散、系统动力学、多智能体和混合系统建模和仿真的工具。它的应用领域包括&#xff1a;物流、供应链、制造生产业、行人交通仿真、行人疏散、城市规划建筑设计、Petri网、城市发展及生态环境、经济学、业务流程、服务系统、…

Linux - 环境变量 - 常规命令 和 内建命令

推荐书籍&#xff0c;《深入理解Linux内核》。鸠摩搜书 | 全网电子书搜索引擎&#xff0c;小说人必备 | Tbox导航 (tboxn.com) 寄存器 你应该知道&#xff0c;代码是被加载到内存当中&#xff0c;cpu才能进行运算的&#xff0c;那么&#xff0c;我们在写函数返回值的时候&…

飞利浦双串口51单片机485网关

主要功能将PC端的数据接收下来&#xff0c;分发到不同的设备&#xff0c;也是轮询设备数据读取回来&#xff0c;打包回传到PC端&#xff0c;数据包包头包尾识别&#xff0c;数据校验&#xff0c;接收超时处理&#xff0c;将协议结构化处理&#xff0c;协议的改动不需要改动程序…

Python 算法高级篇:图的表示与存储优化

Python 算法高级篇&#xff1a;图的表示与存储优化 引言 1. 什么是图&#xff1f;2. 图的基本概念3. 图的表示方法3.1. 临接矩阵表示临接矩阵的优点&#xff1a;临接矩阵的缺点&#xff1a; 3.2. 邻接表表示邻接表的优点&#xff1a;邻接表的缺点&#xff1a; 4. 优化的存储方法…

开机流程、模块管理

一、开机流程 Linux系统组成 kernel 实现进程管理、内存管理、网络管理、驱动程序、文件系统、安全功能等功能rootfs 包括程序和 glibc 库 ​ 程序&#xff1a;二进制执行文件​ 库&#xff1a;函数集合, function, 调用接口&#xff08;头文件负责描述&#xff09; 开机流程…

13.6性能测试理论

一.什么是性能测试 1.定义: 测试人员借助性能测试工具(LoadRunner等),模拟系统在不同场景下(使用高峰期等),对应的性能指标是否达到预期. 2.性能测试和功能测试的区别: a.功能测试依靠人工,性能测试依靠工具. b)功能测试要求软件能正常运行,不管什么场景,性能测试要求软件…

[双指针] (二) LeetCode 202.快乐数 和 11.盛最多水的容器

[双指针] (二) LeetCode 202.快乐数 和 11.盛最多水的容器 快乐数 202. 快乐数 题目解析 (1) 判断一个数是不是快乐数 (2) 快乐数的定义&#xff1a;将整数替换为每个位上的和&#xff1b;如果最终结果为1&#xff0c;就是快乐数 (3) 这个数可能变为1&#xff0c;也可能无…

ESP-IDF编程指南

ESP-IDF 编程指南 - ESP32-C3 - — ESP-IDF 编程指南 v5.1 文档 (espressif.com) ESP-IDF 入门指南 | 乐鑫科技 (espressif.com) ESP-IDF 物联网开发框架 | 乐鑫科技 (espressif.com.cn)

【Git企业开发】第二节.Git 的分支管理

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Git企业级开发 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01;&#xff0…