zoukankan      html  css  js  c++  java
  • 算法学习记录-栈的应用--表达式运算

    前面做了栈的基本操作

    总感觉需要做一个实际的例子来检验一下。

    这里我将用栈来做一个简单的四则运算。

    目标比较简单:

    做一个带小括号(“()”)的四则运算,如果要加入到中括号(“[]”)或者大括号(“{}”),依次类推。

    求一个表达式:

    用下面这个算是做例子,程序最后应该可以算出任何带小括号的运算。

    3+(32-6)*9+5*3-(3*(65-15)/5)+12;

    方法一:后缀法。

    1.了解中缀和后缀表示法

    中缀表示法:刚才的那个算是就是中缀表示法,我们通常看到的数学符号就是中缀表示法,即数字在计算符号的两边。

    后缀表示法:所有的计算符号在数字之后。不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行。

    原理:从左到右遍历表达式,如果是数字则输出,如果是符号:判断该符号与栈顶的符号优先级,

        如果是右括号或者优先级低于栈顶符号,则栈中元素依次出栈并输出,并且将当前符号进栈。

    对上面的式子进行处理:

    后序表达式用处

    当转换成后序表达式后更方便计算表达式的值,如将后序表达式的元素依次进栈直到遇到运算符,这时候从栈中弹出两个元素,再结合运算符计算出这两个数运算的结果(如6-9=3),将其结果压栈(此时栈元素为3 23 -3),然后继续将后序非符号元素压栈,直到遇到运算符。重复之前的操作。。。

    InfixExp(中序表达式)转换PostfixExp(后序表达式)算法

    1)当输入的是操作数时候,直接输出到后序表达式PostfixExp序列中

    2)当输入开括号时候,把它压栈

    3)当输入的是闭括号时候,先判断栈是否为空,若为空,则发生错误并进行相关处理。若非空,把栈中元素依次弹出并输出到Postfix中,知道遇到第一个开括号,若没有遇到开括号,也发生错误,进行相关处理

    4)当输入是运算符op(+、- 、×、/)时候

    a)循环,当(栈非空and栈顶不是开括号and栈顶运算符的优先级不低于输入的运算符的优先级)时,反复操作:将栈顶元素弹出并添加到Postfix中

    b)把输入的运算符op压栈

    5)当中序表达式InfixExp的符号序列全部读入后,若栈内扔有元素,把他们依次弹出并放到后序表达式PostfixExp序列尾部。若弹出的元素遇到空括号,则说明不匹配,发生错误,并进行相关处理

    编写了一个程序如下: 比较烂

      1 #include <iostream>
      2 #include <string>
      3 #include <vector>
      4 #include <stack>
      5 
      6 using namespace std;
      7 
      8 int get_proi(char ch)
      9 {
     10     switch(ch)
     11     {
     12     case '+':
     13     case '-':return 1;
     14 
     15     case '*':
     16     case '/':return 2;
     17 
     18     case '(':
     19     case ')':return 3;
     20     }
     21 }
     22 
     23 void predo(string &str)
     24 {
     25     string ot;
     26     int k=0;
     27     for (int i=0;i<str.size();i++)
     28     {
     29         if (isdigit(str[i]) || isspace(str[i]) || 
     30             str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' ||
     31             str[i] == '(' || str[i] == ')')
     32         {
     33             ot.push_back(str[i]);
     34         }
     35     }
     36     str = ot;
     37 }
     38 
     39 bool in_to_pre(string &str,vector<string> &vec)//中序-->后序
     40 {
     41     vector<string> dest;
     42     stack<string> opstack;
     43     bool flag = false;
     44     int k=0;
     45     int i=0;
     46     //get every elem
     47     while(i<str.size())
     48     {
     49         i=k;
     50         string elem;
     51         if (isdigit(str[i]))
     52         {
     53             while(i<str.size() && isdigit(str[i]))
     54             {
     55                 elem.push_back(str[i]);
     56                 i++;
     57             }
     58             k = i;
     59             vec.push_back(elem);
     60         }
     61         else if (str[i] == '+' || str[i] == '-' || str[i] == '*' || str[i] == '/' || str[i] == '(' || str[i] == ')')
     62         {
     63             elem.push_back(str[i]);
     64             vec.push_back(elem);
     65             i++;
     66             k = i;
     67         }
     68     }
     69     // in to pre
     70     int deep = 0;
     71     for (vector<string>::iterator it = vec.begin();it!=vec.end();it++)
     72     {
     73         string tmp = *it;
     74         
     75         if (isdigit(tmp[0]))
     76         {//1如果是数字直接放入dest中
     77             dest.push_back(tmp);
     78         }
     79         else
     80         {//2如果是操作符则需要判断
     81             //2.1.如果是 “(”,压栈op
     82             if (tmp[0] == '(')
     83             {
     84                 opstack.push(tmp);
     85                 deep++;
     86             }
     87             //2.2.如果是 “)”,出栈直到“(”
     88             else if (tmp[0] == ')')
     89             {
     90                 while(!opstack.empty() && opstack.top().at(0) != '(')
     91                 {
     92                     dest.push_back(opstack.top());
     93                     opstack.pop();
     94                 }
     95                 if (opstack.empty())
     96                 {
     97                     return -1;
     98                 }
     99                 else 
    100                 {
    101                     deep--;
    102                     opstack.pop();
    103                 }
    104             }
    105             //3.不是括号
    106             //3.1 循环,当(栈非空 and 栈顶不是开括号 and 栈顶运算符的优先级 不低于 输入的运算符的优先级)时,反复操作:将栈顶元素退出压入后序栈中
    107             else if (!opstack.empty() && opstack.top().at(0) != '(' && get_proi(opstack.top().at(0)) >= get_proi(tmp[0]))
    108             {
    109                 while(!opstack.empty() && opstack.top().at(0) != '(' && get_proi(opstack.top().at(0)) >= get_proi(tmp[0]))
    110                 {
    111                     dest.push_back(opstack.top());
    112                     opstack.pop();
    113                 }
    114                 opstack.push(tmp);
    115             }
    116             //3.2 压入 操作符 栈中
    117             else
    118             {
    119                 opstack.push(tmp);
    120             }
    121         }
    122     }
    123     while(!opstack.empty())
    124     {
    125         dest.push_back(opstack.top());
    126         opstack.pop();
    127     }
    128     if (deep != 0)
    129     {
    130         return -1;
    131     }
    132     else
    133     {
    134         vec = dest;
    135         return 1;
    136     }
    137 }
    138 
    139 string cacl(string str1,string str2,string op,stack<string> &opt)
    140 {
    141     char oo = op.at(0);
    142     double num1 = atof(str1.c_str());
    143     double num2 = atof(str2.c_str());
    144     double sum=0;
    145     switch(oo)
    146     {
    147     case '+':sum =  num1+num2;break;
    148     case '-':sum =  num1-num2;break;
    149     case '*':sum =  num1*num2;break;
    150     case '/':sum =  num1/num2;break;
    151     }
    152     
    153     char t[256];
    154     string s;
    155 
    156     sprintf(t, "%f", sum);
    157     s = t;
    158     return s;
    159 }
    160 
    161 void do_cacl(vector<string> &vec)
    162 {
    163     stack<string> opt;
    164     for (vector<string>::iterator it = vec.begin();it!=vec.end();it++)
    165     {
    166         string tmp = *it;
    167         if (isdigit(tmp[0]))
    168         {
    169             opt.push(tmp);
    170         }
    171         else
    172         {
    173             string str2 = opt.top();
    174             opt.pop();
    175             string str1 = opt.top();
    176             opt.pop();
    177             
    178             opt.push(cacl(str1,str2,tmp,opt));
    179         }
    180     }
    181     cout<<opt.top();
    182 }
    183 int main()
    184 {
    185     string in;
    186     getline(cin,in);
    187     predo(in);
    188     //not use negative
    189     vector<string> vecpre;
    190     in_to_pre(in,vecpre);
    191     
    192     do_cacl(vecpre);
    193 
    194 
    195     return 0;
    196 }
    View Code

    2.运算的优先级:

  • 相关阅读:
    正则表达式
    内涵函数二
    内置函数
    生成器的推导式 表达式
    函数的闭包 迭代器的使用
    函数的动态参数,命名空间
    函数
    文件的操作
    set 集合 拷贝的操作
    u-boot简介
  • 原文地址:https://www.cnblogs.com/jsgnadsj/p/3408595.html
Copyright © 2011-2022 走看看