实验五——表达式计算

利用二叉树求解表达式的值,编写程序test5.cpp
要求:输入一个算术表达式(以“#”开始,以“#”结束),建立对应的表达式树,输出表达式树的中序遍历序列,以验证表达式树是否建立正确,最后利用此表达式树求解表达式的值并输出。
分析:对于任意一个算术中缀表达式,都可用二叉树来表示。表达式对应的二叉树创建后,利用二叉树的遍历等操作,很容易实现二叉树的求值运算。因此问题的关键就是如何创建表达式树。
假设运算符均为双目运算符,则表达式对应的表达式树中叶子结点均为操作数,分支结点均为运算符。由于创建的表达式树需要准确的表达运算次序,因此,在扫描表达式创建表达式树的过程中,当遇到运算符时不能直接创建结点,而应将其与前面的运算符进行优先级比较,根据比较结果进行处理。这种处理方式见第3章表达式求值算法中的运算符的比较,可以借助一个运算符栈,来暂存已经扫描到的还未处理的运算符。
根据表达式树与表达式对应关系的递归定义,每两个操作数和一个运算符就可以建立一棵表达式二叉树,而该二叉树又可以作为另一个运算符结点的一棵子树。可以另外借助一个表达式树栈,来暂存已建立好的表达式树的根结点,以便其作为另一个运算符结点的子树而被引用。
为实现表达式树的创建算法,可以使用两个工作栈,一个称为OPTR,用以暂存运算符;另一个称为EXPT,用以暂存已建立好的表达式树的根结点。为了便于实现,假设每个表达式均以“#”开始,以“#”结束。
(1) 表达式树的创建算法
① 初始化OPTR和EXPT,将表达式起始符“#”压入OPTR栈
② 扫描表达式,读入第一个字符ch,如果表达式没有扫描完毕至“#”或OPTR栈顶不为“#”时,则循环执行以下操作:
 若ch不是运算符,则以ch为根创建一棵只有根结点的二叉树,且将该树根结点压入EXPT栈,读入下一个ch;
 若ch是运算符,则根据OPTR的栈顶元素和ch的优先级比较结果,做不同处理:
 小于,则ch压入OPTR栈,读入下一个ch;
 大于,则弹出OPTR栈顶运算符,从EXPT栈弹出两个表达式子树的根结点,以该运算符为根结点,以弹出的第二个子树作为左子树,弹出的第一个子树为右子树,创建一棵新二叉树,并将该树根结点压入EXPT栈;
 相等,则OPTR的栈顶元素是“(”且ch是“)”,这时弹出OPTR栈顶的“(”,相当于括号匹配成功,然后读入下一个ch。
(2) 表达式树的求值
① 设变量lvalue和rvalue分别用以记录表达式树中左子树和右子树的值,初始均为0。
② 如果当前结点为叶子(结点为操作数),则返回该结点的数值,否则(结点为运算符)执行以下操作:
 递归计算左子树的值记为lvalue;
 递归计算右子树的值记为rvalue;
 根据当前结点运算符的类型,将lvalue和rvalue进行相应运算并返回。
说明:表达式中的操作数简化为一位正整数。加分项:操作数可以是多位数,也可以是小数。

3、可自行查阅相关关于二叉树表示的求解表达式值的方法,设计相应算法。


表达式计算.gif
//返回函数状态
typedef int Status;

typedef char ElemType;
//二叉树结构
typedef struct BiTNode {
    ElemType data;
    struct BiTNode *lchild, *rchild;
}*BiTree;
//链栈结构
typedef struct StackNode {
    ElemType data;
    BiTree addr;
    struct StackNode *next;
}*LinkStack;
class Stack {
public:
    Status visit(ElemType e);
    Status Init_Stack();
    Status Empty_Stack();
    Status Push_Stack_OPRT(ElemType e);
    Status Push_Stack_EXRT(BiTree T_node);
    ElemType Pop_Stack_OPRT();
    BiTree Pop_Stack_EXPT();
    Status Length_Stack();
    ElemType Get_Stack();
    Status Clear_Stack();
    Status Traverse_Stack();
    Status Destroy_Stack();

    LinkStack top;

    int count;
};


class Tree {
public:
    Status visit(ElemType e);
    //初始化二叉树T
    Status InitBiTree();
    //按先序遍历序列建立二叉链表T
    Status CreateBiTree(BiTree T_node,char *str);
    //检查二叉树T是否为空,空返回1,否则返回0
    bool BiTreeEmpty();
    //求二叉树T的深度并返回该值
    int BiTreeDepth(BiTree T_node);
    //先序遍历二叉树T
    Status PreOrderTraverse(BiTree T_node);
    //中序遍历二叉树T
    Status InOrderTraverse(BiTree T_node);
    //后序遍历二叉树T
    Status PostOrderTraverse(BiTree T_node);
    //销毁二叉树T
    Status DestroyBiTree(BiTree T_node);
    //建立数字二叉树
    BiTree InitTree_Num(ElemType e);
    //建立运算符二叉树
    BiTree InitTree_Op(BiTree R_node,BiTree L_node,ElemType e);
    //计算结果
    double Result(BiTree T_node);
    BiTree T;
};

#include "Resources.h"
#include "cal.h"
#include "LinkStack.h"
#include "Binary_Tree.h"
#include  "Ui.h"
using namespace std;

int main() {
    menu();
    Tree tree;
    Stack OPTR, EXPT;
    ElemType e;
    OPTR.Init_Stack();
    OPTR.Push_Stack_OPRT('#');
    EXPT.Init_Stack();
    while (1) {

        char ch;
        ch = getchar();
        if (ch == '#') {
            OPTR.Destroy_Stack();
            EXPT.Destroy_Stack();
            tree.DestroyBiTree(tree.T);
            system(SCREEN_CLS); //清屏
            int i = 5;
            while (i--) {
                printf("计算器将在");
                setColor(15, 0);
                printf("%d", i);
                setColor(10, 0);
                printf("秒退出,感谢您的使用");
                Sleep(1000);
                system(SCREEN_CLS);
            }
            exit(0);
        } else {
            while (ch != '#' || OPTR.Get_Stack() != '#') {

                if (ch >= '0' && ch <= '9') {
                    //将数字结点地址压入EXPT栈
                    EXPT.Push_Stack_EXRT(tree.InitTree_Num(ch));
                    ch = getchar();
                } else {
                    //判断优先级
                    switch (Priority_Func(OPTR.Get_Stack(), ch)) {
                    case 1:
                        //获取字符
                        e = OPTR.Pop_Stack_OPRT();
                        //将运算符号地址压入EXPT栈
                        EXPT.Push_Stack_EXRT(
                                tree.InitTree_Op(EXPT.Pop_Stack_EXPT(),
                                        EXPT.Pop_Stack_EXPT(), e));
                        break;
                    case 0://将运算符号弹出OPTR栈
                        OPTR.Pop_Stack_OPRT();
                        ch = getchar();
                        break;
                    case -1://将运算符号压入OPRT栈
                        OPTR.Push_Stack_OPRT(ch);
                        ch = getchar();
                        break;
                    default:
                        break;
                    }

                }

            }
            tree.InitBiTree();
            //获取根节点
            tree.T = EXPT.Pop_Stack_EXPT();
            printf("先  序  遍  历:");
            tree.PreOrderTraverse(tree.T);
            printf("\n");
            printf("中  序  遍  历:");
            tree.InOrderTraverse(tree.T);
            printf("\n");
            printf("后  序  遍  历:");
            tree.PostOrderTraverse(tree.T);
            printf("\nResult  =  %.2f\n", tree.Result(tree.T));
            //清除缓存
            fflush(stdin);
        }
        system("pause");
        system(SCREEN_CLS);
        menu2();
    }
    return 0;
}

自学了一下C++,所以还是比较生疏。如果有问题记得和我说一下,谢谢


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容

  • 课程介绍 先修课:概率统计,程序设计实习,集合论与图论 后续课:算法分析与设计,编译原理,操作系统,数据库概论,人...
    ShellyWhen阅读 2,286评论 0 3
  • 目录 0.树0.1 一般树的定义0.2 二叉树的定义 1.查找树ADT 2.查找树的实现2.1 二叉查找树2.2 ...
    王侦阅读 7,200评论 0 3
  • 一直以来,我都很少使用也避免使用到树和图,总觉得它们神秘而又复杂,但是树在一些运算和查找中也不可避免的要使用到,那...
    24K男阅读 6,751评论 5 14
  • 在某些情况下,我们需要对输入字符串表达式进行计算,例如一个字符串为:“1 + 2 * 3”,我们需要计算出它的结果...
    酸菜Amour阅读 1,532评论 0 6
  • 我醒来时自己已经躺在茅草屋里,茅草物的主人说我已经昏迷了十天。我挣扎着想从床上起来,一阵刺痛使我又无力的躺在床上,...
    一年以后5阅读 85评论 0 0