• 逆波兰表达式模型


      其实这个东西早在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] = { '' };
     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
    ", symnum);
     24         error_exp += scan_Infix_to_Suffix(symnum, fp_out);
     25         fprintf(fp_out, "
    ");
     26     }
     27     fprintf(fp_out, "
    Sum of error expression: %d
    ", 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]!='';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,"
    ");
    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
    ", 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! >
    ");
    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 = '';
    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("
    ");
    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

      

  • 相关阅读:
    hph 缓存机制
    递归调用 和 迭代
    多维数组排序
    php curl操作
    JavaScript基本数据类型
    JavaScript基础
    CSS基础布局
    CSS基础样式
    CSS选择器
    CSS3基础
  • 原文地址:https://www.cnblogs.com/Philip-Tell-Truth/p/5814562.html
Copyright © 2020-2023  润新知