逆波兰表达式模型

  其实这个东西早在7月开始的时候我就写好了,本来想等小师妹写好了她的版本再放到网上的。。。无奈她写的实在是太慢了。这个东西还是有改进的空间的,比如升级成浮点模型啥的。

  逆波兰表达式的可以以O(N)时间复杂度处理任意表达式,其实也叫后缀表达式,中缀表达式(就是我们一般看到的表达式(1+1=2)),处理的时候分两个栈,一个符号栈,一个表达式栈:

  (注意我只选二元运算符为例,只处理+-*/和括号)

  1. 如果遇到数字,压入表达式栈

  2. 如果遇到符号

    a. 如果符号是左括号,则直接压入符号栈

    b. 如果是*/符号,且符号栈顶符号为+-或者( ,那么直接压入当前符号即可;如果符号栈顶为*/,弹出符号栈顶符号到表达式栈,压入当前符号。

    c. 如果是+-号,如果符号栈栈顶是*/,则pop符号栈顶到最近的+-号或者(;如果是+-或者(,那就直接弹出上一个+/-号然后压入当前+/-号。

    d. 遇到)就pop符号栈到(

    e. 如果把中缀表达式扫完了符号栈还有东西,那么将符号栈的东西全部pop到表达式栈。

  

  后缀转中缀是上面的逆过程,看代码就知道了。

  之前有想过改成C++的,但是那段时间忙着出Qt,就没写了,这以后可能每三天就写个算法或者复习下以前的数据结构,备战下下一年的面试,就酱~

  以后博客的名字就不分类型拉~感觉直接分类更快。

  1 //main.c
  2
  3 #include <stdio.h>
  4 #include "plug.h"
  5 #include "stack.h"
  6 #include <stdlib.h>
  7 #include <string.h>
  8 #include <math.h>
  9 #include <assert.h>
 10
 11 int main(int argc, char *argv[])
 12 {
 13     int error_exp = 0;
 14     char symnum[81] = { ‘\0‘ };
 15     FILE *fp_in = fopen("D:\\input.txt", "r");
 16     FILE *fp_out = fopen("D:\\output.txt", "w");
 17     if (fp_in == NULL)
 18         exit(1);
 19
 20     while (!feof(fp_in))
 21     {
 22         fscanf(fp_in, "%s", symnum);
 23         fprintf(fp_out, " Infix expression:  %s\n", symnum);
 24         error_exp += scan_Infix_to_Suffix(symnum, fp_out);
 25         fprintf(fp_out, "\n");
 26     }
 27     fprintf(fp_out, "\nSum of error expression: %d\n", error_exp);
 28
 29     return EXIT_SUCCESS;
 30 }
 31
 32 int scan_Infix_to_Suffix(char *input, FILE *fp)
 33 {
 34     int i = 0;
 35     Stack_manager *num_stack = allcoate_stack_man(),
 36                   *stack_man = allcoate_stack_man(),
 37                   *sym_man = allcoate_stack_man();
 38     Stack **list = (Stack **)malloc(sizeof(Stack)*MAX);//存指向栈的指针的表
 39
 40     for (;input[i]!=‘\0‘;i++)
 41     {
 42         if (input[i] >= ‘0‘ && input[i] <= ‘9‘)
 43             //把所有连续的数字先结合起来形成一个数,如果遇到符号,则把num栈转化为数字存入主栈中
 44             push_in_int(num_stack, input[i] - ‘0‘);
 45         //遇到‘(‘,优先级最高,直接压栈
 46         else if (input[i] == ‘(‘)
 47             push_in_char(sym_man, input[i]);
 48         else if (input[i] == ‘*‘ || input[i] == ‘/‘)
 49         {
 50             //遇到乘除号,如果栈中含有(‘+‘或者‘-‘),压入符号栈
 51             if (input[i - 1] != ‘)‘)
 52                 push_in_int(stack_man, combine_Stack_to_Num(num_stack));
 53
 54             //错误处理
 55             if ((stack_man->top->type == is_int && input[i] == ‘/‘)//除数不能为0
 56                 || i == 0                                           //开头出现单独乘除号
 57                 || input[i - 1] == ‘+‘ || input[i - 1] == ‘-‘       //两个符号连续
 58                 || input[i - 1] == ‘*‘ || input[i - 1] == ‘/‘
 59                 )
 60             {
 61                 error(sym_man, stack_man, num_stack, list, fp);
 62                 return 1;
 63             }
 64
 65             if (sym_man->top == NULL
 66                 || (sym_man->top->sym == ‘+‘ || sym_man->top->sym == ‘-‘)
 67                 && sym_man->top->sym == ‘(‘)
 68                 //除非处理闭括号,否则看到‘(‘什么符号都压栈
 69                 push_in_char(sym_man, input[i]);
 70
 71             //否则弹出上一个乘除号
 72             else if (sym_man->top->sym == ‘*‘ || sym_man->top->sym == ‘/‘)
 73             {
 74                 push_in_char(stack_man, sym_man->top->sym);
 75                 pop_out(sym_man);
 76                 push_in_char(sym_man, input[i]);
 77             }
 78         }
 79         else if (input[i] == ‘+‘ || input[i] == ‘-‘)
 80         {
 81             if (input[i - 1] != ‘(‘ && input[i - 1] != ‘)‘ && i != 0)
 82                 push_in_int(stack_man, combine_Stack_to_Num(num_stack));
 83
 84             //错误处理(开头连续两个加减号或者连续三个符号)
 85             if (i == 1 && (input[i - 1] == ‘+‘ || input[i - 1] == ‘-‘))
 86             {
 87                 error(sym_man, stack_man, num_stack, list, fp);
 88                 return 1;
 89             }
 90             if (i >= 2 && (input[i - 1] == ‘+‘ || input[i - 1] == ‘-‘)
 91                 && (input[i - 2] == ‘+‘ || input[i - 1] == ‘-‘ || input[i - 1] == ‘*‘ || input[i - 1] == ‘/‘
 92                 || input[i - 1] == ‘(‘ || input[i - 1] == ‘)‘))
 93             {
 94                 error(sym_man, stack_man, num_stack, list, fp);
 95                 return 1;
 96             }
 97
 98             //如果前一个为符号或者左括号或者没有符号,则为数的正负,压入数栈
 99             if (i == 0
100                 || input[i - 1] == ‘+‘ || input[i - 1] == ‘-‘
101                 || input[i - 1] == ‘*‘ || input[i - 1] == ‘/‘
102                 || input[i - 1] == ‘(‘)
103                 push_in_char(num_stack, input[i]);
104
105             //如果有比+-优先级更高的运算符(‘*‘,‘/‘),则把符号弹出直到上一次的加减号或者‘(‘为止
106             else if (!sym_man->top
107                 || sym_man->top->sym == ‘*‘ || sym_man->top->sym == ‘/‘
108                 || sym_man->top->sym == ‘(‘)//符号为‘(‘的情况合并到这里了
109             {
110                 for (;sym_man->top != NULL
111                     && sym_man->top->sym != ‘(‘;)
112                 {
113                     push_in_char(stack_man, sym_man->top->sym);
114                     pop_out(sym_man);
115                 }
116                 push_in_char(sym_man, input[i]);
117             }
118             //如果上一个符号是+-号,那么直接弹出上一个加减号到主栈,并且把当前符号压入符号栈
119             else if (sym_man->top->sym == ‘+‘ || sym_man->top->sym == ‘-‘)
120             {
121                 push_in_char(stack_man, sym_man->top->sym);
122                 pop_out(sym_man);
123                 push_in_char(sym_man, input[i]);
124             }
125         }
126         else if (input[i] == ‘)‘)
127         {
128             push_in_int(stack_man, combine_Stack_to_Num(num_stack));
129
130             for (;sym_man->top != NULL && sym_man->top->sym != ‘(‘;)
131             {
132                 push_in_char(stack_man, sym_man->top->sym);
133                 pop_out(sym_man);
134             }
135             if (sym_man->top->sym != ‘(‘)//只有右括号括号,出错
136             {
137                 error(sym_man, stack_man, num_stack, list, fp);
138                 return 1;
139             }
140             pop_out(sym_man);//弹掉‘(‘
141         }
142         else//其他情况均为不合法的情况,out
143         {
144             error(sym_man, stack_man, num_stack, list, fp);
145             return 1;
146         }
147     }
148     //最后应该还有一个数字的
149     if (input[i - 1] != ‘)‘)
150         push_in_int(stack_man, combine_Stack_to_Num(num_stack));
151
152     //把剩下的符号弹入栈中
153     for (;sym_man->top!=NULL;)
154     {
155         if (sym_man->top->sym == ‘(‘)//只有左括号,出错
156         {
157             error(sym_man, stack_man, num_stack, list, fp);
158             return 1;
159         }
160         push_in_char(stack_man, sym_man->top->sym);
161         pop_out(sym_man);
162     }
163     copy_Stack_to_List(list, stack_man);
164     print_list(list, stack_man->node_sum, fp);
165     caculate_Infix(list, stack_man->node_sum,fp);
166
167     //正常退出
168     delete_stack(&sym_man);
169     delete_stack(&stack_man);
170     delete_stack(&num_stack);
171     free(list);
172     return 0;
173 }
174
175 int combine_Stack_to_Num(Stack_manager *const num_stack)
176 {
177     int sum = 0, num_pow = 0;
178     for (;num_stack->top != NULL;)
179     {
180         if (num_stack->top->type == is_int)
181             sum += (int)(num_stack->top->num*pow(10.0, (double)num_pow++));
182         else
183             sum = num_stack->top->sym == ‘+‘ ? sum : -sum;
184         pop_out(num_stack);
185     }
186     return sum;
187 }
188
189 void copy_Stack_to_List(Stack **const list, Stack_manager *const stack_man)
190 {
191     int j = stack_man->node_sum - 1;
192     Stack *tmp = stack_man->top;
193     for (;j != -1;j--, tmp = tmp->prev)
194         list[j] = tmp;
195 }
196
197 void get_Ans(Stack_manager *const s, char operation)
198 {
199     assert(s->top != NULL || s->top->prev != NULL);
200     int tmp1 = s->top->num, tmp2 = s->top->prev->num, ans;
201     if (operation == ‘+‘)
202         ans = tmp1 + tmp2;
203     else if (operation == ‘-‘)
204         ans = tmp2 - tmp1;
205     else if (operation == ‘*‘)
206         ans = tmp1*tmp2;
207     else if (operation == ‘/‘)
208         ans = tmp2 / tmp1;
209     //连续pop两次,把tmp1和tmp2弹出去
210     pop_out(s); pop_out(s);
211     //把答案压栈
212     push_in_int(s, ans);
213 }
214
215 void print_list(Stack **const list, int const node_sum, FILE *fp)
216 {
217     int i;
218     fprintf(fp,"Suffix expression: ");
219     for (i = 0;i < node_sum;i++)
220     {
221         if (list[i]->type == is_sym)
222             fprintf(fp, "%c ", list[i]->sym);
223         else
224             fprintf(fp, "%d ", list[i]->num);
225     }
226     fprintf(fp,"\n");
227 }
228
229 void caculate_Infix(Stack **const suffix_list, int const node_sum, FILE *fp)
230 {
231     int i;
232     Stack_manager *stack_man = allcoate_stack_man();
233     for (i = 0;i < node_sum;i++)
234     {
235         if (suffix_list[i]->type == is_int)
236             push_in_int(stack_man, suffix_list[i]->num);
237         else if (suffix_list[i]->type == is_sym)
238             get_Ans(stack_man, suffix_list[i]->sym);
239     }
240     fprintf(fp, "           Answer: %d\n", stack_man->top->num);
241
242     delete_stack(&stack_man);
243 }
244
245 void error(Stack_manager *s1, Stack_manager *s2, Stack_manager *s3, Stack**L,FILE *fp)
246 {
247     fprintf(fp, "< illegal expression! >\n");
248     delete_stack(&s1);
249     delete_stack(&s2);
250     delete_stack(&s3);
251     free(L);
252 }
 1 //plug.h
 2
 3 #ifndef Suffix_to_Infix
 4 #define Suffix_to_Infix
 5 #define MAX 256
 6 #include <stdio.h>
 7
 8 enum symbol_or_interget { is_sym, is_int };
 9
10 typedef struct _stack
11 {
12     char sym;
13     int num, type;
14     struct _stack *prev;
15 }Stack;
16
17 typedef struct _stack_manager
18 {
19     int node_sum;
20     struct _stack *top;
21 }Stack_manager;
22
23 void push_in_int(Stack_manager *const, const int);
24 void push_in_char(Stack_manager *const, const char);
25 void pop_out(Stack_manager *const);
26 int scan_Infix_to_Suffix(char *,FILE *);
27 int combine_Stack_to_Num(Stack_manager *const);
28 void copy_Stack_to_List(Stack **const, Stack_manager *const);
29 void caculate_Infix(Stack **const, int const, FILE *);
30 void get_Ans(Stack_manager *const, char);
31 void print_list(Stack **const,int const, FILE *);
32 void error(Stack_manager *, Stack_manager *, Stack_manager *, Stack**, FILE *fp);
33
34 #endif // !Suffix_to_Infix
 1 //stack.cpp
 2
 3 #include "plug.h"
 4 #include "stack.h"
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7
 8 Stack_manager *allcoate_stack_man(void)
 9 {
10     Stack_manager *stack_man = (Stack_manager *)malloc(sizeof(Stack_manager));
11     stack_man->top = NULL, stack_man->node_sum = 0;
12     return stack_man;
13 }
14
15 void push_in_int(Stack_manager *const s_head, const int item)
16 {
17     Stack *tmp = NULL;
18
19     tmp = (Stack *)malloc(sizeof(Stack));
20
21     tmp->prev = s_head->top;
22     tmp->num = item, tmp->sym = ‘\0‘;
23     tmp->type = is_int;
24
25     s_head->node_sum++;
26     s_head->top = tmp;
27 }
28
29 void push_in_char(Stack_manager *const s_head, const char item)
30 {
31     Stack *tmp = NULL;
32
33     tmp = (Stack *)malloc(sizeof(Stack));
34
35     tmp->prev = s_head->top;
36     tmp->sym = item, tmp->num = 0;
37     tmp->type = is_sym;
38
39     s_head->node_sum++;
40     s_head->top = tmp;
41 }
42
43 void pop_out(Stack_manager *const s)
44 {
45     Stack *tmp = s->top->prev;
46     s->node_sum--;
47     free(s->top);
48     s->top = tmp;
49 }
50
51 void delete_stack(Stack_manager **stack_man)
52 {
53     for (;(*stack_man)->top != NULL;)
54         pop_out(*stack_man);
55     free(*stack_man);
56     *stack_man = NULL;
57 }
58
59 void print_stack(Stack_manager *const s)
60 {
61     Stack *tmp = s->top;
62     for (;tmp != NULL;tmp = tmp->prev)
63     {
64         if (tmp->type == is_sym)
65             printf("%c ", tmp->sym);
66         else
67             printf("%d ", tmp->num);
68     }
69     printf("\n");
70 }
 1 //stack.h
 2
 3 #ifndef STACK
 4 #define STACK
 5
 6 void push_in_int(Stack_manager *const, const int);
 7 void push_in_char(Stack_manager *const, const char);
 8 void pop_out(Stack_manager *const);
 9 Stack_manager *allcoate_stack_man(void);
10 void delete_stack(Stack_manager **);
11 void print_stack(Stack_manager *const);
12
13 #endif // !STACK

  

时间: 2024-08-15 10:44:39

逆波兰表达式模型的相关文章

逆波兰表达式

1696:逆波兰表达式 总时间限制: 1000ms 内存限制: 65536kB 描述 逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 + 3) * 4的逆波兰表示法为* + 2 3 4.本题求解逆波兰表达式的值,其中运算符包括+ - * /四个. 输入 输入为一行,其中运算符和运算数之间都用空格分隔,运算数是浮点数. 输出 输出为一行,表达式的值.可直接用prin

lintcode 中等题:Evaluate Reverse Polish notation逆波兰表达式求值

题目 逆波兰表达式求值 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2", "1", "+", "3", "*"] -> ((2 + 1) * 3) -> 9 ["4", "13", "5", "/", "+"]

求解逆波兰表达式的值

题目: Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are +, -, *, /. Each operand may be an integer or another expression. Some examples:   ["2", "1", "+", "3", "*"

[Leetcode] evaluate reverse polish notation 计算逆波兰表达式

Evaluate the value of an arithmetic expression in Reverse Polish Notation. Valid operators are+,-,*,/. Each operand may be an integer or another expression. Some examples: ["2", "1", "+", "3", "*"] -> (

栈的操作实现逆波兰表达式的计算

代码如下: #include <stdio.h> #include <stdlib.h> #include <ctype.h> #define STACK_INIT_SIZE 20 #define STACKINCREMENT 10 #define MAXBUFFER 10 typedef double ElemType; typedef struct { ElemType *base; ElemType *top; int StackSize; }sqStack; v

C++实现 逆波兰表达式计算问题

C++实现 逆波兰表达式计算问题 #include <iostream> #include <string> using namespace std; class Stack { private: int size; int top; float *listArray; public: Stack(int sz=20); ~Stack(); bool push(float it);//入栈 bool pop(float& it);//出栈 bool isEmpty();//

续前篇-关于逆波兰表达式的计算

相对于逆波兰表达式的转换,逆波兰表达的计算可谓简单不少. 具体计算方法参考:http://www.cnblogs.com/vpoet/p/4659546.html 这里也大致梳理一下: 1.新建一个栈将逆波兰表达式的数字依次压入栈中 2.当遇到运算符时,出栈两个数同时将运算结果压栈 3.重复步骤2直到计算计算,栈中的元素即为逆波兰表达式的计算结果. 实现如下: 1 #include <iostream> 2 #include <stack> 3 using namespace st

逆波兰表达式的C实现

复习下数据结构,用栈简单实现逆波兰表达式,参考文档: http://www.nowamagic.net/librarys/veda/detail/2307 http://www.nowamagic.net/librarys/veda/detail/2306 直接上代码: /** *code by lichmama from cnblogs.com *@逆波兰表达式的C实现 *算术支持的运算模式: * 四则运算: * 操作数不得大于9: * 中间数(即运算当中的临时变量)不得超过127 **/ #

逆波兰表达式(后缀表达式)

前/中/后缀表达式的转换 自然表达式转换为前/中/后缀表达式,其实是很简单的.首先将自然表达式按照优先级顺序,构造出与表达式相对应的二叉树,然后对二叉树进行前/中/后缀遍历,即得到前/中/后缀表达式. 举例说明将自然表达式转换成二叉树: a×(b+c)-d ① 根据表达式的优先级顺序,首先计算(b+c),形成二叉树 ②然后是a×(b+c),在写时注意左右的位置关系 ③最后在右边加上 -d 然后最这个构造好的二叉树进行遍历,三种遍历的顺序分别是这样的: ① 前序遍历:根-左-右 ② 中序遍历:左-