数据结构+二叉遍历算法的应用

news2024/11/26 4:44:53

一、问题描述

编写一个程序,先用二叉树表示一个简单算术表达式,树的每一个 结点包括一个运算符或运算数。在简单算术表达式中只包含+、-、 *、/和一位正整数且格式正确(不包含括号),并且要按照先乘除后 加减的原则构造二叉树。如图 7.35 所示为“1+2*3-4/5”算术表达 式对应的二叉树。然后由对应的二叉树计算该表达式的值。

二、问题解决

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
 
typedef struct BTreeNode 
{ 
 char data; 
 struct BTreeNode* lchild; 
 struct BTreeNode* rchild; 
} BTNode; 
 
float calculate(BTNode* T) 
{ 
 if(T==NULL) 
 return 0; 
 if(T->data <='9'&&T->data >='0') 
 return (T->data-'0'); //将 char 类型转化为 int 类型进行
计算 
 else 
 { 
 switch(T->data) //T->data 为运算符,则有左右孩子节
点且不空 
 { 
 case'+': return calculate(T->lchild) + calculate(T->rchild); 
break; 
 case'-': return calculate(T->lchild) - 
calculate(T->rchild); break; 
 case'*': return calculate(T->lchild) * 
calculate(T->rchild); break;  case'/': return calculate(T->lchild) / 
calculate(T->rchild); break; 
 } 
 } 
} 
 
char* input_cheak_str() //字符串动态输入与检测函数 
{ 
 printf("请输入一个简单算术表达式(一位正整数且只有+-*/无括
号):\n"); 
 int ch_num=0; 
 char ch,*str; 
 str=(char*)malloc(sizeof(char)); 
 while((ch=getchar())!='\n') //设置按照输入字符数变化的字符数
组 
 { 
 if(ch_num%2==1) //下标为奇数,字符应为运算符号 
 { 
 if(ch!='+' && ch!='-' && ch!='*' && ch!='/') 
 { 
 printf(" 第 %d 个 字 符 输 入 不 合 法 ! 应 为 “ +-*/ ” 之 一
",ch_num+1); 
 return 0; 
 } 
 } 
 else //下标为偶数,字符应该为数字 
 { 
 if(!(ch>='0' && ch<='9')) 
 { 
 printf("第%d 个字符输入不合法!应为 0 至 9 数字之一
",ch_num+1); 
 return 0; 
 } 
 } 
 str[ch_num]=ch; 
 str=(char*)realloc(str,(++ch_num+1)*sizeof(char)); // ∵
ch_num 为字符数组下标,而 realloc 参数为字符个数 
 } //∴新
开数组长度参数为下标+2,相当于参数为 num++后的 num+1 
 if(str[ch_num-1]=='+' || str[ch_num-1]=='-' || str[ch_num-1]=='*' || str[ch_num-1]=='/') 
 { //若最
后一个字符为运算符则输入不合法 
 printf("最后一个字符输入不合法!应为数字!",ch_num+1); 
 return 0; 
 } 
 str[ch_num]='\0'; //串结尾设置串结束符 
 return str; 
} 
 
BTNode* create_tree(char *str) 
{ 
 int itemCount=0,ASCount=0,len=strlen(str),i; //AS 意为 addSub 加减
法,itemCount 为加减项计数,ASCount 为加减符号计数 
 BTNode **ASItem,**ASSign,*root,*p; //ASItem 指针数组存
放加减项节点指针,ASSign 指针数组存放加减符号节点指针 
 ASItem=(BTNode**)malloc((len/2+1)*sizeof(BTNode*)); 
 ASSign=(BTNode**)malloc((len/2)*sizeof(BTNode*)); 
 if(str[0]=='\0') //加减项节点数应该
为加减符号数加一.所以 itemCount==ASCount+1 
 return NULL; 
 for(i=0;i<len/2;i++) //指针数组置空 
 ASSign[i]=NULL; 
 for(i=0;i<len/2+1;i++) 
 ASItem[i]=NULL; 
 for(i=0;i<len;i++) //读取 str 字符数组 
 { 
 if(str[i]<='9' && str[i]>='0') 
 { 
 p=(BTNode*)malloc(sizeof(BTNode)); 
 p->data=str[i]; 
 p->lchild=p->rchild=NULL; 
 } 
 else if(str[i]=='+'||str[i]=='-') 
 { 
 ASItem[itemCount++]=p; //将 p 节点放入加减项数组 
 p=(BTNode*)malloc(sizeof(BTNode)); 
 p->data=str[i]; 
 ASSign[ASCount++]=p; 
 } //将加减符号节点指针放入 ASSign 数组,因有符号节点的孩子必不为空且创建过程不会访问其孩子节点,故无需置空 
 else //str[i]符号为乘除的情况 
 { 
 root=(BTNode*)malloc(sizeof(BTNode)); 
 root->data=str[i]; //将*,/作为数据存入根节点数据
域 
 root->lchild=p; //p 一定为数字或*,/节点(都是已
构造好的) 
 p=(BTNode*)malloc(sizeof(BTNode)); 
 p->data=str[++i]; //此时 p 为当前节点的下一个节
点,此时 str[++i]必为数字,且下一个访问的 str 必为符号 
 p->lchild=p->rchild=NULL; 
 root->rchild=p; //根节点的右孩子连上此节点 
 p=root; //整个根节点构造完毕,传入 p 
 } 
 } 
 ASItem[itemCount]=p; 
 ASSign[0]->lchild=ASItem[0]; //第一个符号节点左孩子连第一
个项节点 
 ASSign[0]->rchild=ASItem[1]; 
 for(i=1;i<ASCount;i++) //以加减法符号节点作为子树根
节点,加减法之间的项的节点为子树根节点的孩子节点 
 { 
 ASSign[i]->lchild=ASSign[i-1]; //除第一个节点以外的加减符号
节点左孩子都连上一个符号节点 
 ASSign[i]->rchild=ASItem[i+1]; //右孩子都连项节点 
 } 
 return ASSign[ASCount-1]; 
 } 
 
 void disp_tree(BTNode *T) 
 { 
 if(T != NULL) 
 { 
 printf("%c", T->data); 
 if(T->lchild != NULL || T->rchild != NULL) 
 { 
 printf("("); // 有孩子结点时才输出( 
 disp_tree(T->lchild); // 递归处理左子树 
 if(T->rchild != NULL) // 有右孩子结点时才输出,  printf(","); 
 disp_tree(T->rchild); // 递归处理右子树 
 printf(")"); // 有孩子结点时才输出) 
 } 
 } 
 } 
 
int main () 
{ 
 char *str=input_cheak_str(); 
 disp_tree(create_tree(str)); 
 printf("\n"); 
 printf("%3.2f",calculate(create_tree(str))); 
 return 0; 

三、代码分析

实现简单算术表达式求值,首先要判断输入的表达式是否合法,即只包含 +、-、*、/且正整数的位数为一位。 构建二叉树算法主体思路是将正确(输入时经过检测)的一位正整数无括 号的简单表达式字符串,以加减法为分界线(因为会先计算乘除法)将表达式分 割成若干个加减项后再将已生成的加减项节点与加减符号项节点交替连接成 树,其中每个加减项节点都是其子树。 计算简单算术表达式的值则是要将 char 类型的数字转化为 int 类型的数 字,然后利用 switch 语句进行加减乘除的运算。

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

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

相关文章

QT5生成独立运行的exe文件

目录 1 生成独立运行的exe文件1.1 设置工程Release版本可执行文件存储路径1.2 将工程编译成Release版本 2 使用QT5自带的windeployqt拷贝软件运行依赖项3 将程序打包成一个独立的可执行软件exe4 解决QT5 This application failed to start because no Qt platform plugin could…

批量快递中问题件筛选技巧大揭秘

批量快递中问题件筛选技巧大揭秘&#xff1a;固乔快递查询助手的强大功能 在电商行业日益繁荣的今天&#xff0c;快递服务成为了连接商家与消费者的关键纽带。然而&#xff0c;随着订单量的激增&#xff0c;如何高效处理并筛选出快递中的问题件&#xff0c;成为了许多商家面临…

shuishusihui

互斥量 使用互斥量可以用于保护某些临界资源&#xff0c;同一时间只能有一个任务来使用它。 使用互斥量会引入其他问题&#xff0c;比如说优先级反转&#xff0c;于是提出了优先级继承等方法解决问题 任务通知 任务通知就是通知任务&#xff0c;前边都是多对多的关系&#xff0…

算法解析——双指针算法(3)数据匹配

欢迎来到博主的专栏——算法解析 博主ID&#xff1a;代码小豪 文章目录 LCR179、查找总价格为目标值的两个商品leetcode11——盛水最多的容器leetcode611——有效三角形的个数 我们前面已经盘点了两种双指针算法的使用场景&#xff0c;现在来看看最常见的一种。 通常&#xff0…

社交电商系统开发功能定制

社交电商系统开发功能定制是一项综合性的服务&#xff0c;它涉及到需求分析、界面设计、功能开发、系统测试以及上线后的持续维护。以下是社交电商系统开发中应考虑的关键功能点&#xff1a; 需求分析和规划&#xff1a;开发前&#xff0c;企业需要明确业务需求&#xff0c;包…

【数据分析:一篇文章带你掌握Pandas高级可视化技巧】

前言&#xff1a; &#x1f49e;&#x1f49e;大家好&#xff0c;我是书生♡&#xff0c;本阶段和大家一起分享和探索数据分析的数据可视化&#xff0c;本篇文章主要讲述了&#xff1a;掌握Pandas高级可视化技巧等等。欢迎大家一起探索讨论&#xff01;&#xff01;&#xff01…

docker的swarm技术

docker中swarm技术 docker swarm技术是docker社区提供的docker的集群管理调度工具&#xff0c;通过api来管理多个主机上的docker&#xff0c;通过overlay网络来实现不同主机之间容器的通信与访问。实现容器的调度&#xff0c;资源的分配&#xff0c;以及副本。 docker swarm中…

愛ㄉ粗麵體字體欣赏

愛ㄉ粗麵體字體字体欣赏&#xff0c;英文名AddaNoodle 下载到字体档后&#xff0c;首先打开字体文件预览看看&#xff0c;超可愛的&#xff5e; 最近流行的可愛字體&#xff0c;VIVISTICKER-愛ㄉ粗麵體 QQ 軟軟的筆觸不只適合有溫度的限動 放在貼文或介紹文字都超級適合 還找不…

汇编语言指令 jmp: jmp word ptr、jmp dword ptr、jmp 寄存器、jmp 段地址:偏移地址

1. 转移地址在内存中的jmp指令有2种形式 1.1 jmp word ptr 内存单元地址 jmp word ptr 内存单元地址是段内转移指令&#xff0c;也就是说该指令只修改IP值&#xff0c;其功能是控制CPU下一条执行的指令是一个字&#xff08;2个字节&#xff09;内存中存放的偏移地址所指向的指…

【Python】函数入门(下)

3&#xff09;&#xff09;* ** ​​​​​​注意&#xff1a;也遵循位置传参在前面&#xff0c;按关键字传参在后面。 代码示例&#xff1a; def func(*args,**kwargs):print(args,kwargs) 该函数中的参数会自动根据传参的方式不同&#xff08;即&#xff1a;按位置…

家电行业实施数字工厂管理系统前要做好哪些准备

家电企业在实施数字工厂管理系统前&#xff0c;需要做好以下准备&#xff1a; 一、明确目标与需求 数字化转型目标&#xff1a;明确数字化转型的具体目标&#xff0c;如提高生产效率、降低生产成本、优化库存管理、提升产品质量等。这些目标将指导整个数字工厂管理系统的选择…

STM32学习笔记09-SPI通信

目录 SPI通信简介 硬件电路 移位示意图 SPI基本时序单元 SPI时序 W25Q64简介 硬件电路 W25Q64框图 Flash操作注意事项 SPI外设简介 SPI框图 SPI基本结构 主模式全双工连续传输 非连续传输 软件/硬件波形对比 SPI应用 软件SPI读写W25Q64 硬件SPI读写W25Q64 SP…

在复制 PowerPoint (PPT) 文件时,其中嵌入或者链接的 Excel 文件能够自动创建一个新的实例,而不是继续引用原始的 Excel 文件。

问题&#xff1a; 在复制 PowerPoint (PPT) 文件时&#xff0c;其中嵌入或者链接的 Excel 文件能够自动创建一个新的实例&#xff0c;而不是继续引用原始的 Excel 文件。 解答&#xff1a; 导入已有的excel实测是不行的

为什么程序员应该学习多种语言?

前言 有一句老话适用于所有软件开发人员&#xff1a;知道得越多&#xff0c;成长得越多。程序员学习多种编程语言后、‌可以加速学习新技术、‌拓展认知和视野。‌ 对于程序员来说&#xff0c;‌精通一门编程语言意味着对该语言有深入的理解和熟练的运用&#xff0c;‌这为程…

LLMCompiler执行数学计算的案例

LLMCompiler执行数学计算的案例 LLMCompiler执行数学计算的案例案例代码LLMCompiler的LangGrap结构可视化Tasks DAG可视化完整运行日志 LLMCompiler执行数学计算的案例 这是一个使用LLMCompiler执行数学运算的完整案例&#xff0c;通过设置’ print_dag 参数&#xff0c;可以完…

vme背板 介绍

VME背板是基于VME总线规范的背板,它是VME系统中的重要组成部分,主要负责模块之间的连接和数据传输。VMEbus(Versa Module Eurocard bus)是一种广泛应用于工业控制、军事、航空航天以及电信领域的模块化计算机总线标准。VME背板是VME系统的核心组件之一,它不仅提供了物理支…

思路超清晰的 LVS-NAT 模式实验部署

目录 一、实验原理 1、实验基础配置图 2、实验原理 二、实验环境准备 1、准备四台红帽9的主机 2、四台主机的基础配置 &#xff08;1&#xff09;client 1&#xff09;配置主机名&#xff1a;client 2&#xff09;配置ip:172.25.254.200 &#xff08;2&#xff09;lv…

DAMA学习笔记(十四)-数据管理成熟度评估

1.引言 能力成熟度评估&#xff08;Capability Maturity Assessment&#xff0c;CMA&#xff09;是一种基于能力成熟度模型&#xff08;Capability Maturity Model&#xff0c;CMM&#xff09;框架的能力提升方案&#xff0c;描述了数据管理能力初始状态发展到最优化的过程。CM…

掌握VS Code调试技巧:解决Scrapy模块导入中断问题

介绍 在使用Scrapy进行网页爬取时&#xff0c;Visual Studio Code&#xff08;VS Code&#xff09;作为一款流行的代码编辑器&#xff0c;凭借其强大的调试功能&#xff0c;成为了许多开发者的首选。然而&#xff0c;部分开发者在调试Scrapy爬虫时&#xff0c;常遇到程序在模块…

《剑指offer》题目 C++详细题解

JZ15 二进制中1的个数 核心考点&#xff1a;二进制计算 思路一&#xff1a;使用一个循环&#xff0c;因为我们知道整型变量只有32位&#xff0c;所以循环结束的条件就是到32&#xff0c;从最低位开始&#xff0c;逐位检查数字 n 的二进制表示&#xff0c;利用位运算中的与运算…