题目:
动态表达式求值 功能:
(1) 输入并保存公式到文件。(公式中的操作数用字母代替,计算时给出具体值)
(2) 将公式载入到表达式二叉树
(3) 输入操作数的具体值,计算结果
需求分析:
- 本演示程序中,表达式变量限制为26个英文字母,大小写均可。运算符支持“+,-,*,/,^”,允许括号。
- 演示程序以用户和计算机对话方式执行,即在计算机终端上显示提示信息之后,用户按格式输入数据,计算结果显示在其后,公式部分会保存在与程序同目录的文件“data.txt”中。
使用说明:
- 执行过程:输入一行公式,创建二叉树,输入'数据组数n'和每组数据'变量个数m',之后每组数据输入m行,每行为变量名,空格,变量值的形式。计算并输出结果。
- 测试数据:
a^b+c/(d-e)
3 5
a 2
b 3
c 43
d 5
e -3
a 1.1
b 2
c 1
d 143
e 334
a 3.4
b 2
c 10
d 5
e 0.1
n
结果:
13.375
1.20475
13.6008
概要设计:
顺序栈存储结构
Struct {
Type_a sta[MAXX];
Int top_a;//记录栈顶
}
二叉树存储结构:
struct Data {
char val;
struct Data *lch,*rch;
}
TNode new_Node(char val)
操作结果:创建并返回值为val的数树节点
void build(*s,len)
操作结果:根据公式s,创建表达式二叉树
double Tra(t)
操作结果:根据带入数据计算表达式树的值
详细设计:
Part1 建树
参照通过栈求表达式值的算法。
之前数字栈的操作与二叉树操作一一对应。
比如取出数字栈顶两个数3,5,求3+5 = 8放进数字栈
这次栈中存二叉树节点
对应取出栈顶两个值为3,5的子树的根a,b,新建节点值为‘+’左儿子a,右儿子b.放回栈中
例子
3*(4-1)
数字3 4 1
符号 *(-
数字3 3
符号*
数字9
符号
Part2 计算
double char_to_val[257];
char_to_val[‘a’]代表变量a的值
通过递归求解
如果某个节点是变量x,返回char_to_val[x];
否则该点的值是操作R(+-*/^)是 左子树的值R右子树的值。
程序:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define MAXX 10000
char sta[MAXX];int top_a;
double char_to_val[257];
typedef struct Data {
char val;
struct Data *lch,*rch;
}Node,*TNode;
TNode new_Node(char val) {
TNode tp = (TNode)malloc(sizeof(Node));
tp->lch = tp->rch = NULL;
tp->val = val;
return tp;
}
TNode stt[MAXX];
int top_t;
int Level(char c) {
return (c=='^')*2 + (c=='*'||c=='/')*1 + (c=='+'||c=='-')*0;
}
void Out() {
char c = sta[top_a--];
TNode tmp = new_Node(c);
tmp->lch = stt[top_t-1];
tmp->rch = stt[top_t];
stt[--top_t] = tmp;
}
void build(char *s,int len) {
int i;
for (i = 0; i < len; i++) {
char c = s[i];
if (isalpha(c)) {
stt[++top_t] = new_Node(c);
} else if (c == ')') {
while(sta[top_a] != '(') Out();
top_a--;
} else if (c == '(') {
sta[++top_a] = c;
} else {
while(top_a && sta[top_a]!='(' && Level(sta[top_a])>=Level(c)) Out();
sta[++top_a] = c;
}
}
while(top_a) Out();
}
double calc(double a,char opt,double b) {
if (opt == '^') return pow(a,b);
if (opt == '+') return a+b;
if (opt == '-') return a-b;
if (opt == '*') return a*b;
if (opt == '/') return a/b;
return 0;
}
double Tra(TNode t) {
if (isalpha(t->val)) return char_to_val[(int)t->val];
return calc(Tra(t->lch),t->val,Tra(t->rch));
}
int main() {
FILE *fp = fopen("data.txt","w");
char s[MAXX];
char tmp;
int t,i;
while(1) {
printf("请输入表达式:\n");
scanf("%s",s);
fprintf(fp,"%s\n",s);//保存公式到文件
top_a = top_t = 0;
build(s,strlen(s));//将公式载入到表达式二叉树
char val_x; double val_n;
int cas,tot;
printf("请输入'数据组数'和每组数据'变量个数':\n");
scanf("%d%d",&cas,&tot);//输入操作数的具体值,计算结果
for (t = 1; t <= cas; t++) {
for (i = 1; i <= tot; i++) {
scanf("%*c%c%lf",&val_x,&val_n);
char_to_val[(int)val_x] = val_n;
}
printf("%g\n",Tra(stt[top_t]));
}
printf("继续?y/n\n");
scanf("%*c%c",&tmp);
if (tmp == 'n') break;
}
fclose(fp);
return 0;
}
调试分析: