四则运算式
合集下载
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
输入时以一连串的字符输入中缀表达式,中缀表达式中每 个元素,括号,运算符,以及数字的每一位都是存储在一 个字符中。存储中缀表达式的是一个string类的数组, 存入时,进行判断,,每个运算符,括号,即一串数字都 21 分别存入string类数组的一个元素中。
+
21+23*(12-16)
23 * ( 12 16 )
算法的具体步骤
bool putin_judge()//输入判断并存入中缀表达 式 int I=0;//全局变量I node* build(string a[])//建立存储中缀表达式 的完全二叉树 void exchange(node* subroot,Queue *queue) //遍历完全二叉树,在队列中建立后缀表达式 void calculate(Queue queue,Stack2 stack2) //通过入栈出栈的方式计算后缀表达式的值 int main()//主函数,调用上述函数
详细设计
①数字字符串为表达式的第一个元素或在左括号之后
a+b*c 或者 (a+b......) Root/root0 ?
root1
a
root1->value=a[I];
详细设计
物理数据类型
class Stack2//堆栈的类 {private: float *Array; int fence,maxsize,size; public: Stack2(int sz){}//构建栈 ~Stack2(){}//删除栈 void clear(){}//清空栈 bool push(const float &it){} //压入栈 bool pop(float &it){}//弹出栈 };
详细设计
while(a[i]!=0) int I=0;//全局变量I { if(a[i]是数字字符串) node* build(string a[]) {if( {int flag0=0;//flag0=0表示是第一次输入 , 为表达式的第一个元素或在左括号之后)① else(上次读出的是运算符)② 1表示上次输入的是+,-运算符, if(a[i]是括号) //2表示上次输入的是*,/运算符, { if(a[i]是左括号) node *Root=new node,*root0=new node, { if(是某对括号内第一个左括号)调用自身③ else(前面有一个运算符)调用自身④} *root1=new node; else(即a[i]是右括号) //Root起到某棵树的根结点作用 {if(括号内仅有一个数字)返回⑤ root0=Root;Root->left=root1 else(括号内含有一个式子)返回⑥}} ;//root1代表某棵树的第一个数字, if(a[i]是运算符) 或唯一的数字 { if(第一次读出运算符)⑦ else { if(上次读出的是'+','-'运算符)⑧ else(上次读出的是‘*’,‘/'运算符)⑨ }} if(读出的仅为一个数字)return root1; else(读出的为一个式子) return Root;}
数据结构第4次小班讨论
四则运算表达式求值
物联1102 胡标 20110808217
背景与问题描述
• 背景
在工资管理软件中,不可避免的要用到公式 的定义及求值等问题。对于数学表达式的计算, 虽然可以直接对表达式进行扫描并按照优先级逐 步计算,但也可以将中缀表达式转换为逆波兰表 达式,这样更容易处理。 问题描述 四则运算表达式求值,将四则运算表达式用 中缀表达式,然后转换为后缀表达式,并计算结 果。
栈顶
16 12 23 21
栈顶
12-16 23 21
栈顶 23*(12-16) 21
栈顶 21+23*(12-16)
概要设计
• • • • 21+23*(12-16) 21 23 12 16 - * + 最先读取21,然后读取23,再然后是12,16,-,*,+ 按照刚才的运算步骤,需要依次读出21,23,12,16,-, *,+。读入与读出顺序恰好满足队列的特点
需求分析
输出的形式:输出由输入的中缀表达式转化而来 的后缀表达式,整数与整数,整数与符号,符号 与符号之间有空格输出,并输出表达式计算得到 的值。 如,输入中缀表达式:21+23*(12-16) 输出:21 23 12 16 -*+ 159
概要设计 • 抽象数据类型
• 数据对象:中缀表达式中的 整数,运算符,括号。 • 数据关系:四则运算符都是 二元运算符,左右两边为数 字或四则运算式子,任何四 则运算符又都可以根据预算 符的优先顺序分为一个运算 符及其两边的数字或式子。 四则运算式子的中缀表达式 的括号仅起到改变运算符优 先顺序的作用。于是四则运 算的中缀表达式满足完全二 叉树的结构特点。
概要设计
• 队列的基本操作有 • 新建队列Queue(int sz),其为队列类的构造函数,需要 一个整形变量作为参数确定数组长度,作用是为指向数组 中元素的指针开辟空间,确定数组长度 • 销毁队列~Queue(),为队列类的析构函数,不需任何参 数,其释放指针的空间,销毁队列 • 清空队列void clear(),不需任何参数,其清空数组中的 所有元素 • 入队bool enqueue(string &it),需要string类的引用 作为参数。将参数中的值存入数组中指针所指向的元素, 同时指针后移一位,操作成功返回true,否则返回false。 • 出队bool dequeue(string &it),需要指向string类的 引用作为参数,返回布尔型数据,将数组的第一个元素的 值给参数操作成功返回true,否则返回false。
详细设计
• • • • • • • • • • • • • • • • • • • • • • bool putin_judge() {char a[100],c[4]; cin>>a; if(a中不存在过长的连续数字) {while(a[i]!=0) {if(a[i]是运算符) {if(上一次输入的是运算符或左括号,或者是第一次输入)报错 else {b[j]=a[i];j++;i++;}}} else{if(a[i]是左右括号) {if(a[i]是左括号) {if(上次输入的是右括号或数字) 报错 else {b[j]=a[i];j++;i++}} else{ if(上次输入的是左括号或运算符) 报错 else {b[j]=a[i];j++;i++}}} else(a[i]是数字) { if(上次输入的是右括号)报错; else { int k=0;while(a[i]是数字){ b[j][k]=a[i];k++;i++;}k++;}} else//即输入的是不合法的字符 报错;}}}} if(错误) return false; else return true;}
(1-2)*(3-4)
* +
1
234ຫໍສະໝຸດ 概要设计• 21+23*(12-16) • 21 23 12 16 - * + • 观察这个后缀表达式,我 们发现是在后缀表达式中 数字中最后的12和16首先 进行计算,得到的值再和 23计算,得到的值最后再 和21计算。可以使用栈的 形式实现之。即,最先使 21入栈,然后依次使 23,12,16入栈。12与16最 先弹出,最先计算,值压 入,再弹出,弹出23,计 算,值压入,再弹出,弹 出21,计算,再压入。
需求分析
输入的形式和输入值的范围:从键盘输入符合要求的中缀表 达式,如果输入的中缀表达式不符合规范或不正确,则显 示错误。输入的内容包括整数,字符”(“,”)”“+”, “-”,“*”,“/”。输入回车表示结束。 输入的中缀表达式不符合规范的情况包括: ①第一个输入的数据是“)”,“+”,“-”,“*”, “/”。 ②输入整数后输入“(“。 ③输入运算符后输入运算符或“)”。 ④输入“(”后输入“)”或运算符。 ⑤输入“)”后输入整数或“(”。 ⑥输入除规定运算符和“(”,“)”外的其他字符。 ⑦以运算符结尾, ⑧输入的数字过长
概要设计
算法思想
建立完全二叉树,根据运算符,括号,操作数之间 的 关系,建立起二叉树,该过程在我的算法中比较复杂,将 在后面讲到。 后序遍历二叉树,得到后缀表达式的形式。 计算后缀表达式的值,使用栈,已在前面讲到。
*
1 2- 3 4 - *
+
(1-2)*(3-4)
1 2 3 4
概要设计
中缀表达式的输入与存储,
概要设计
• 栈的基本操作有 • 新建栈Stack(int sz),其为栈类的构造函数,需要一个整 形变量作为参数确定数组长度,作用是为指向数组中元素 的指针开辟空间,确定数组长度 • 销毁栈~Stack(),为栈类的析构函数,不需任何参数, 其释放指针的空间,销毁队栈 • 清空栈void clear(),不需任何参数,其清空数组中的所 有元素 • 压入栈bool push(string &it),需要string类的引用作 为参数。将参数中的值存入数组中指针所指向的元素,同 时指针后移一位,操作成功返回true,否则返回false。 • 弹出栈bool pop(string &it),需要指向string类的引用 作为参数,返回布尔型数据,将数组的指针所指向的元素 的值给参数,同时指针前移一位。操作成功返回true,否 则返回false。
详细设计
物理数据类型 class node string b[100];//存放表达式中数字,运 { public: 算符,括号的string类数组 string value; int i; node *left,*right; node() class Queue//队列的类 { i=0; { left=NULL; private: string *Array; right=NULL;} int fence,maxsize; node(const node& root) public: Queue(int sz){}//队列的构建 { value=root.value; ~Queue(){}//队列的销毁 left=root.left; void clear(){}//队列的清空 right=root.right; bool enqueue(string &it){}//入队 bool dequeue(string &it){}//出队 i=root.i;} }; };//二叉树的结点类型
队首
21 23 12 16 - * +
栈顶
16 12 23 21
栈顶 23*(12-16)
栈顶
12-16 23 21
21
栈顶 21+23*(12-16)
概要设计
• • • • • 由以上分析知道, 对象:数字,运算符 对象关系:完全二叉树,队列,栈 其中完全二叉树的基本操作有 建立二叉树node* build(string a[]),其需要存储中缀 表达式的数组作为参数,返回指向结点类型的指针,将中 缀表达式中各元素转换到完全二叉树中存储。 • 后序遍历二叉树 void exchange(node* subroot,Queue *queue),其 需要指向二叉树的根结点的指针与指向队列类型的指针作 为参数,无返回值,它按照一定的遍历方式访问树中各结 点,并将它们的值存入队列,以在队列中形成后缀表达式。
2 1 + 2 3 * ( 1 2 — 1 6)
概要设计
将存储的数字字符串转化为数字。 将存储在字符串内的0~9数字转化为数字,数字 字符的ASCII 码减0的ASCII码得到的ASCII码值, 恰好是其数值
2 1 2 3
2+‘0’ 1+‘0’ 2+‘0’ 3+‘0’
概要设计
程序分为四大模块
第一模块 输入中缀表达式,通过键盘向计算机输入一串含中缀表达式 的字符数组,同时判断其是否正确,正确则存入一string类数组。否报 错。 第二模块 构建二叉树,将string类的个元素存入结点,根据一定的规则连成 完全二叉树。 第三模块 遍历二叉树并将树的各结点存入队列,在队列中形成后缀表达式。 第四模块 使队列中的数据出队,通过入栈出栈的方式计算得到后缀表达中的 值。
+
21+23*(12-16)
23 * ( 12 16 )
算法的具体步骤
bool putin_judge()//输入判断并存入中缀表达 式 int I=0;//全局变量I node* build(string a[])//建立存储中缀表达式 的完全二叉树 void exchange(node* subroot,Queue *queue) //遍历完全二叉树,在队列中建立后缀表达式 void calculate(Queue queue,Stack2 stack2) //通过入栈出栈的方式计算后缀表达式的值 int main()//主函数,调用上述函数
详细设计
①数字字符串为表达式的第一个元素或在左括号之后
a+b*c 或者 (a+b......) Root/root0 ?
root1
a
root1->value=a[I];
详细设计
物理数据类型
class Stack2//堆栈的类 {private: float *Array; int fence,maxsize,size; public: Stack2(int sz){}//构建栈 ~Stack2(){}//删除栈 void clear(){}//清空栈 bool push(const float &it){} //压入栈 bool pop(float &it){}//弹出栈 };
详细设计
while(a[i]!=0) int I=0;//全局变量I { if(a[i]是数字字符串) node* build(string a[]) {if( {int flag0=0;//flag0=0表示是第一次输入 , 为表达式的第一个元素或在左括号之后)① else(上次读出的是运算符)② 1表示上次输入的是+,-运算符, if(a[i]是括号) //2表示上次输入的是*,/运算符, { if(a[i]是左括号) node *Root=new node,*root0=new node, { if(是某对括号内第一个左括号)调用自身③ else(前面有一个运算符)调用自身④} *root1=new node; else(即a[i]是右括号) //Root起到某棵树的根结点作用 {if(括号内仅有一个数字)返回⑤ root0=Root;Root->left=root1 else(括号内含有一个式子)返回⑥}} ;//root1代表某棵树的第一个数字, if(a[i]是运算符) 或唯一的数字 { if(第一次读出运算符)⑦ else { if(上次读出的是'+','-'运算符)⑧ else(上次读出的是‘*’,‘/'运算符)⑨ }} if(读出的仅为一个数字)return root1; else(读出的为一个式子) return Root;}
数据结构第4次小班讨论
四则运算表达式求值
物联1102 胡标 20110808217
背景与问题描述
• 背景
在工资管理软件中,不可避免的要用到公式 的定义及求值等问题。对于数学表达式的计算, 虽然可以直接对表达式进行扫描并按照优先级逐 步计算,但也可以将中缀表达式转换为逆波兰表 达式,这样更容易处理。 问题描述 四则运算表达式求值,将四则运算表达式用 中缀表达式,然后转换为后缀表达式,并计算结 果。
栈顶
16 12 23 21
栈顶
12-16 23 21
栈顶 23*(12-16) 21
栈顶 21+23*(12-16)
概要设计
• • • • 21+23*(12-16) 21 23 12 16 - * + 最先读取21,然后读取23,再然后是12,16,-,*,+ 按照刚才的运算步骤,需要依次读出21,23,12,16,-, *,+。读入与读出顺序恰好满足队列的特点
需求分析
输出的形式:输出由输入的中缀表达式转化而来 的后缀表达式,整数与整数,整数与符号,符号 与符号之间有空格输出,并输出表达式计算得到 的值。 如,输入中缀表达式:21+23*(12-16) 输出:21 23 12 16 -*+ 159
概要设计 • 抽象数据类型
• 数据对象:中缀表达式中的 整数,运算符,括号。 • 数据关系:四则运算符都是 二元运算符,左右两边为数 字或四则运算式子,任何四 则运算符又都可以根据预算 符的优先顺序分为一个运算 符及其两边的数字或式子。 四则运算式子的中缀表达式 的括号仅起到改变运算符优 先顺序的作用。于是四则运 算的中缀表达式满足完全二 叉树的结构特点。
概要设计
• 队列的基本操作有 • 新建队列Queue(int sz),其为队列类的构造函数,需要 一个整形变量作为参数确定数组长度,作用是为指向数组 中元素的指针开辟空间,确定数组长度 • 销毁队列~Queue(),为队列类的析构函数,不需任何参 数,其释放指针的空间,销毁队列 • 清空队列void clear(),不需任何参数,其清空数组中的 所有元素 • 入队bool enqueue(string &it),需要string类的引用 作为参数。将参数中的值存入数组中指针所指向的元素, 同时指针后移一位,操作成功返回true,否则返回false。 • 出队bool dequeue(string &it),需要指向string类的 引用作为参数,返回布尔型数据,将数组的第一个元素的 值给参数操作成功返回true,否则返回false。
详细设计
• • • • • • • • • • • • • • • • • • • • • • bool putin_judge() {char a[100],c[4]; cin>>a; if(a中不存在过长的连续数字) {while(a[i]!=0) {if(a[i]是运算符) {if(上一次输入的是运算符或左括号,或者是第一次输入)报错 else {b[j]=a[i];j++;i++;}}} else{if(a[i]是左右括号) {if(a[i]是左括号) {if(上次输入的是右括号或数字) 报错 else {b[j]=a[i];j++;i++}} else{ if(上次输入的是左括号或运算符) 报错 else {b[j]=a[i];j++;i++}}} else(a[i]是数字) { if(上次输入的是右括号)报错; else { int k=0;while(a[i]是数字){ b[j][k]=a[i];k++;i++;}k++;}} else//即输入的是不合法的字符 报错;}}}} if(错误) return false; else return true;}
(1-2)*(3-4)
* +
1
234ຫໍສະໝຸດ 概要设计• 21+23*(12-16) • 21 23 12 16 - * + • 观察这个后缀表达式,我 们发现是在后缀表达式中 数字中最后的12和16首先 进行计算,得到的值再和 23计算,得到的值最后再 和21计算。可以使用栈的 形式实现之。即,最先使 21入栈,然后依次使 23,12,16入栈。12与16最 先弹出,最先计算,值压 入,再弹出,弹出23,计 算,值压入,再弹出,弹 出21,计算,再压入。
需求分析
输入的形式和输入值的范围:从键盘输入符合要求的中缀表 达式,如果输入的中缀表达式不符合规范或不正确,则显 示错误。输入的内容包括整数,字符”(“,”)”“+”, “-”,“*”,“/”。输入回车表示结束。 输入的中缀表达式不符合规范的情况包括: ①第一个输入的数据是“)”,“+”,“-”,“*”, “/”。 ②输入整数后输入“(“。 ③输入运算符后输入运算符或“)”。 ④输入“(”后输入“)”或运算符。 ⑤输入“)”后输入整数或“(”。 ⑥输入除规定运算符和“(”,“)”外的其他字符。 ⑦以运算符结尾, ⑧输入的数字过长
概要设计
算法思想
建立完全二叉树,根据运算符,括号,操作数之间 的 关系,建立起二叉树,该过程在我的算法中比较复杂,将 在后面讲到。 后序遍历二叉树,得到后缀表达式的形式。 计算后缀表达式的值,使用栈,已在前面讲到。
*
1 2- 3 4 - *
+
(1-2)*(3-4)
1 2 3 4
概要设计
中缀表达式的输入与存储,
概要设计
• 栈的基本操作有 • 新建栈Stack(int sz),其为栈类的构造函数,需要一个整 形变量作为参数确定数组长度,作用是为指向数组中元素 的指针开辟空间,确定数组长度 • 销毁栈~Stack(),为栈类的析构函数,不需任何参数, 其释放指针的空间,销毁队栈 • 清空栈void clear(),不需任何参数,其清空数组中的所 有元素 • 压入栈bool push(string &it),需要string类的引用作 为参数。将参数中的值存入数组中指针所指向的元素,同 时指针后移一位,操作成功返回true,否则返回false。 • 弹出栈bool pop(string &it),需要指向string类的引用 作为参数,返回布尔型数据,将数组的指针所指向的元素 的值给参数,同时指针前移一位。操作成功返回true,否 则返回false。
详细设计
物理数据类型 class node string b[100];//存放表达式中数字,运 { public: 算符,括号的string类数组 string value; int i; node *left,*right; node() class Queue//队列的类 { i=0; { left=NULL; private: string *Array; right=NULL;} int fence,maxsize; node(const node& root) public: Queue(int sz){}//队列的构建 { value=root.value; ~Queue(){}//队列的销毁 left=root.left; void clear(){}//队列的清空 right=root.right; bool enqueue(string &it){}//入队 bool dequeue(string &it){}//出队 i=root.i;} }; };//二叉树的结点类型
队首
21 23 12 16 - * +
栈顶
16 12 23 21
栈顶 23*(12-16)
栈顶
12-16 23 21
21
栈顶 21+23*(12-16)
概要设计
• • • • • 由以上分析知道, 对象:数字,运算符 对象关系:完全二叉树,队列,栈 其中完全二叉树的基本操作有 建立二叉树node* build(string a[]),其需要存储中缀 表达式的数组作为参数,返回指向结点类型的指针,将中 缀表达式中各元素转换到完全二叉树中存储。 • 后序遍历二叉树 void exchange(node* subroot,Queue *queue),其 需要指向二叉树的根结点的指针与指向队列类型的指针作 为参数,无返回值,它按照一定的遍历方式访问树中各结 点,并将它们的值存入队列,以在队列中形成后缀表达式。
2 1 + 2 3 * ( 1 2 — 1 6)
概要设计
将存储的数字字符串转化为数字。 将存储在字符串内的0~9数字转化为数字,数字 字符的ASCII 码减0的ASCII码得到的ASCII码值, 恰好是其数值
2 1 2 3
2+‘0’ 1+‘0’ 2+‘0’ 3+‘0’
概要设计
程序分为四大模块
第一模块 输入中缀表达式,通过键盘向计算机输入一串含中缀表达式 的字符数组,同时判断其是否正确,正确则存入一string类数组。否报 错。 第二模块 构建二叉树,将string类的个元素存入结点,根据一定的规则连成 完全二叉树。 第三模块 遍历二叉树并将树的各结点存入队列,在队列中形成后缀表达式。 第四模块 使队列中的数据出队,通过入栈出栈的方式计算得到后缀表达中的 值。