栈用例——中缀表达式转后缀表达式、二叉树求表达式

一、中缀表达式转后缀表达式

  • 中缀表达式:就是我们平时书写的带括号的标准四则运算表达式,如9+(3-1)*3+10/2
  • 后缀表达式:没有括号的,常用于编译器计算表达式,如9 3 1 - 3 * + 10 2 / +

编译器无法直接去计算中缀表达式,而是会先将中缀表达式利用【栈】先转换为后缀表达式。

转换算法
  • 1、从左至右遍历中缀表达式(字符串),遇到数字则输出(暂时只做打印),遇到运算符则入栈先保存。
    2、若遇到")"右括号,则要将栈顶至最近的左括号的所有操作符依次出栈全部输出打印,注意括号都不打印。
    3、符号入栈也有规则。若是当前要入栈的符号优先级高于栈顶的符号,则直接入栈;否则(优先级相同或者低于),先将栈顶一个符号出栈,然后再将当前符号和新的栈顶符号比较,依次循环。
    4、当所有的数字都输出时,将栈中的符号也一次出栈输出。

二、编译器如何将后缀表达式用于实际的计算?利用二叉树构建表达式树

1、先用后缀表达式构建表达式树,设输入后缀表达式为ab+cde+**,得到表达式树的过程如下图:

前两个符号是操作数,因此创建两棵单结点树并将指向它们的指针压入栈中。



接着,"+"被读入,因此指向两棵树的指针被弹出,形成一棵新的树,并将指向它的指针压入栈中。


image

然后,c,d和e被读入,在单个结点树创建后,指向对应的树的指针被压入栈中。

接下来读入"+"号,因此两棵树合并。



继续进行,读入"*"号,因此,弹出两棵树的指针合并形成一棵新的树,"*"号是它的根。

最后,读入一个符号,两棵树合并,而指向最后的树的指针被留在栈中。
表达式树

【一种算法来把后缀表达式转变成表达式树。】我们一次一个符号地读入表达式。如果符号是操作数,那么就建立一个单结点树并将它推入栈中。如果符号是操作符,那么就从栈中弹出两棵树T1和T2(T1先弹出)并形成一棵新的树,该树的根就是操作符,它的左、右儿子分别是T2和T1。然后将指向这颗树的指针压入栈中。
完整步骤看这里:https://blog.csdn.net/buaa_shang/article/details/9124075

2、将表达式树进行中序遍历,可以分别计算各个子树的结果,最后计算出整个表达式的结果(a+b)*(c*(d+e))

【问题】 可以看到中序遍历出来的又是一个普通的四则运算中缀表达式。那为什么要引入后缀表达式做这个转换?
以开头的例子:中缀9+(3-1)*3+10/2==》后缀9 3 1 - 3 * + 10 2 / +==》表达式树==》中序遍历==>9 + 3 - 1 * 3 + 10 / 2
相当于只是做了一个去括号的操作,但是在遍历的同时将每两个叶子节点的数字计算出了结果,然后依次递归返回时将最后的计算结果输出。

typedef struct      
{     //其实也可以用union类型来做,更省空间
    int num;    //存储整形数字
    char ch;    //存储运算符号
} ElemType; 
typedef struct BiTNode 
{ 
    ElemType data; 
    struct BiTNode *lchild,*rchild; 
} BiTNode,*BiTree; 

//中序遍历运算并输出表达式
int Travel(BiTree T) 
{ 
    int result; 
    if (T->lchild==NULL&&T->rchild==NULL){ 
        printf("%d",T->data.num); 
       result=T->data.num; 
    } 
    else
    { 
        printf("("); 
        int num1=Travel(T->lchild); 
        printf("%c",T->data.ch);   //中序遍历打印各个非叶子节点的符号值
        int num2=Travel(T->rchild); 
        printf(")"); 
      //对每两个叶子节点计算运算值。由此可见后序遍历也是可以计算的。
        switch (T->data.ch)
        { 
          case '+':result=num1+num2; break; 
          case '-':result=num1-num2; break; 
          case '*':result=num1*num2; break; 
          case '/':result=num1/num2; break; 
        } 
    } 
    return re; 
} 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容