算术表达式的转换

题目描述

小明在学习了数据结构之后,突然想起了以前没有解决的算术表达式转化成后缀式的问题,今天他想解决一下。
   因为有了数据结构的基础小明很快就解出了这个问题,但是他突然想到怎么求出算术表达式的前缀式和中缀式呢?小明很困惑。聪明的你帮他解决吧。

输入

 输入一算术表达式,以\'#\'字符作为结束标志。(数据保证无空格,只有一组输入)

输出

 输出该表达式转换所得到的前缀式 中缀式 后缀式。分三行输出,顺序是前缀式 中缀式 后缀式。

示例输入

a*b+(c-d/e)*f#

示例输出

+*ab*-c/def
a*b+c-d/e*f
ab*cde/-f*+
代码操作归结为:
将中缀式转化为后缀式;
将后缀式转化为表达式树;
将表达式树先序,中序,后序遍历得前缀式,中缀式,后缀式;
  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 
  5 struct node
  6 {
  7     char ch;
  8     struct node *l,*r;
  9 };
 10 char s[110],s1[110],s2[110];
 11 int q;
 12 
 13 void post()
 14 {
 15     int x = 0, y = 0;
 16     for(q = 0; s[q] != '#'; q++)
 17     {
 18         if(s[q] >= 'a' && s[q] <= 'z')
 19             s1[x++] = s[q];
 20         else if(s[q]  == '(')
 21             s2[y++] = s[q];
 22         else if(s[q] == ')')
 23         {
 24             while(s2[y-1] != '(')
 25             {
 26                 s1[x] = s2[y-1];
 27                 x++;
 28                 y--;
 29             }
 30             y--;
 31         }
 32         else if(s[q] == '+' || s[q] == '-')
 33         {
 34             while(y != 0 && s2[y-1] != '(')
 35             {
 36                 s1[x] = s2[y-1];
 37                 x++;
 38                 y--;
 39             }
 40             s2[y++] = s[q];
 41         }
 42         else if(s[q] == '*' || s[q] == '/')
 43         {
 44             while(y != 0 &&(s2[y-1]=='*'||s2[y-1]=='/'))
 45             {
 46                 s1[x] = s2[y-1];
 47                 x++;
 48                 y--;
 49             }
 50             s2[y++] = s[q];
 51         }
 52     }
 53     while(y != 0)
 54     {
 55         s1[x] = s2[y-1];
 56         x++;
 57         y--;
 58     }
 59     s1[x] = '\0';
 60 }
 61 void preorder(struct node *p)
 62 {
 63     if(p == NULL)
 64         return;
 65     printf("%c",p->ch);
 66     preorder(p->l);
 67     preorder(p->r);
 68 }
 69 void inorder(struct node *p)
 70 {
 71     if(p == NULL)
 72         return;
 73     inorder(p->l);
 74     printf("%c",p->ch);
 75     inorder(p->r);
 76 }
 77 void postorder(struct node *p)
 78 {
 79     if(p == NULL)
 80         return;
 81     postorder(p->l);
 82     postorder(p->r);
 83     printf("%c",p->ch);
 84 }
 85 
 86 int main()
 87 {
 88     int i,top = 0;
 89     scanf("%s",s);
 90     //转化为后缀式
 91     post();
 92 
 93     //转化成表达式树(链栈)
 94     struct node *po[110] = {NULL},*pi;
 95     for(i = 0; i < q; i++)
 96     {
 97         if(s1[i] >= 'a' && s1[i] <= 'z')
 98         {
 99             pi = (struct node *)malloc(sizeof(struct node));
100             pi->ch = s1[i];
101             pi->l = NULL;
102             pi->r = NULL;
103             po[top++] = pi;
104         }
105         else
106         {
107             pi = (struct node *)malloc(sizeof(struct node));
108             pi->ch = s1[i];
109             pi->r = po[top-1];//注意先是右子树再是左子树
110             top--;
111             pi->l = po[top-1];
112             top--;
113             po[top++] = pi;
114         }
115     }
116 
117     //分别遍历
118     preorder(po[0]);
119     printf("\n");
120     inorder(po[0]);
121     printf("\n");
122     postorder(po[0]);
123     printf("\n");
124     return 0;
125 
126 }
View Code

下面来讨论如何根据表达式建立一棵树。我们知道在表达式树中,只有度为2的树杈结点与度为0的叶子节点,并且树杈节点上都存放运算符,叶子节点都存放操作数。比如由表达式1+2*3创建的树是这样的: 

每一个叶子结点有一个确定的值,对于每一个运算符结点,也可以看做它代表一个值,其值为左子树的值与右子树的值按照结点中存储的运算符计算后的结果。如结点 ’+’的值为“1+右子树的值”,而右子树的值为它的左子树的值乘以它的右子树的值,即”2*3”,所以表达式的值就是根节点的值”1+2*3”。
    由上述递归的定义不难看出,建立表达式树就是建立树中的每一个结点,将每一个结点链接起来就是整棵树。而在建立深度低的结点时要将其左右指针指向之前建立的深度比它高一级的结点 (如’*’要指向’2’和’3’,而’+’又要指向’*’)。这样我们可以用栈来存放每次建立的结点,按照优先级(表达式为中缀型)或顺序扫描表达式(表达式为波兰式与逆波兰式)建立每一个结点。建立结点的顺序即为表达式求值的顺序。如果扫描到操作数则直接新建一个左右指针为空的结点,并压入结点栈中(存放结点指针)。遇到运算符时首先新建一个结点,然后从栈中依次弹出两个结点,并让新建立的结点的左右指针域指向它们。当所有结点建立完毕时,如果表达式没有错误(这里假设输入表达式正确),这时栈中应该只剩下一个结点,它就是所建立的表达式的根结点。
 

转载于:https://www.cnblogs.com/LK1994/p/3221196.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
算术表达式转换为后缀表达式的步骤如下: 1. 创建一个空的栈和一个空的输出队列。 2. 从左到右扫描中缀表达式。 3. 如果扫描到的是操作数,将其加入输出队列。 4. 如果扫描到的是左括号,将其压入栈中。 5. 如果扫描到的是右括号,则将栈中的元素依次弹出并加入输出队列,直到遇到左括号为止。左括号右括号都不输出到结果队列。 6. 如果扫描到的是运算符,判断其优先级: - 如果该运算符的优先级低于或等于栈顶运算符的优先级,则将栈顶运算符弹出并加入输出队列,直到栈为空或者栈顶运算符优先级低于该运算符。 - 将该运算符压入栈中。 7. 重复步骤2到6,直到扫描完整个中缀表达式。 8. 如果栈中还有运算符,将它们依次弹出并加入输出队列。 9. 输出队列中的元素就是后缀表达式。 例如,将中缀表达式 "5 + 4 * 3 - 2" 转换为后缀表达式: 1. 创建一个空的栈和一个空的输出队列。 2. 从左到右扫描中缀表达式,首先遇到操作数 "5",将其加入输出队列。 3. 遇到运算符 "+",将其压入栈中。 4. 遇到操作数 "4",将其加入输出队列。 5. 遇到运算符 "*",由于 "*" 的优先级高于 "+",所以将 "*" 压入栈中。 6. 遇到操作数 "3",将其加入输出队列。 7. 遇到运算符 "-",由于 "-" 的优先级低于 "*",所以将 "*" 弹出并加入输出队列,然后将 "-" 压入栈中。 8. 遇到操作数 "2",将其加入输出队列。 9. 扫描完整个表达式后,将栈中剩余的运算符依次弹出并加入输出队列,得到后缀表达式 "5 4 3 * + 2 -"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值