CCF-CSP认证考试准备第十四天 201912-3 化学方程式


### Day14:1.201912-3

#### 1.201912-3:化学方程式(大模拟,字符串解析,嵌套结构处理(括号,用栈))
(1)先获取40分(未处理左右括号)->60分(处理一对括号)->学习满分代码
(2)
##### 1.思路一(不断解析字符串,直到最小单元为化学式,然后来计算):
(1) 对于每个方程式,**`isBalanced`函数将方程式分为左右两部分("="号分割)**,分别调用`parseSide`解析左右两侧的化学式。
(2)**`parseSide`函数负责处理方程式的一侧,它会调用`parseFormula`来解析具体的化学式(“+”号和i (3)**`parseFormula`使用栈来处理括号嵌套结构**,通过逐个字符扫描,将化学式中的每个元素及其数量存储到**哈希表**中。
(4) **最后,通过比较左右两边的元素数量**(**比较两个哈希表**),判断是否配平。
(5)代码:
```
#include

using namespace std;

//系数字符串转整形,i是引用,自动++
int parseNumber(string s,int &i){
    int sum=0;
    while(i='0' && s[i]<='9'){
        sum=sum*10+s[i]-'0';
        i++;
    }
    return sum==0?1:sum;//无系数默认为1(可以变通拓展) 
}

//提取一个的化学式的元素及系数(核心) 
map parseFormula(string s,int qianXi){
    map res;
    stack> st; 
    st.push(map());//先加一层栈顶 
    for(int i=0;i         if(s[i]=='('){
            //进入新的一层括号 
            st.push(map());
            i++;
        }
        else if(s[i]==')'){
            //提取一个层级的map,乘上括号后面的系数 
            i++;
            int kuohaoXi=parseNumber(s,i);//这个函数更改i,下面不用i++了 
            auto top_ele=st.top();//top_ele为map和类型 
            st.pop();//弹出这层,下面的 s.top()为上一层 
            for(auto &x:top_ele){//x为pair类型 
                st.top()[x.first]+=x.second*kuohaoXi;//改变上一层的,加上这一层的为这一层每个string的int(下标系数)乘上这一层的括号系数 
            }
        }
        else{//处理这一层括号内的单个元素 
            string ele; 
            ele+=s[i++];//提取大写字母
            while(i='a' && s[i]<='z'){
                //提取小写字母 
                ele+=s[i++];
            } 
            int xiaXi=parseNumber(s,i);//提取下标系数
            st.top()[ele]+=xiaXi; 
        }
    }
    //将栈顶的map乘上前面系数放到res的map里面 
    for(auto &x:st.top()){
        res[x.first]+=x.second*qianXi;
    }
    return res;
}

//提取一侧的化学方程式的元素及系数 
map parseSide(string s){
    map res;
    for(int i=0;i         int qianXi=parseNumber(s,i);//获取前面系数 
        int start=i;//一个化学式的开始
        while(i         auto formula_ele=parseFormula(s.substr(start,i-start),qianXi);//解析一个化学式,获取元素哈希表
        //把每一个化学式哈希表加入一侧方程式哈希表中 
        for(auto x:formula_ele){
            res[x.first]+=x.second;
        }
        i++;//跳过+号 
    }
    return res;
}

//判断左右两个化学方程式是否相等 
bool isBalanced(string s){
    auto pos=s.find('=');//通过"="号划分
    string left=s.substr(0,pos);
    string right=s.substr(pos+1);
    auto left_ele=parseSide(left);//解析一测方程式 
    auto right_ele=parseSide(right);
    return left_ele==right_ele;
}

int main(){
    int n;
    cin>>n;
    while(n--){
        string s;
        cin>>s;
        cout<<(isBalanced(s)?"Y":"N")<     }
    return 0;
}
```
(6)栈使用核心(括号嵌套):
1.确定栈的元素,本题为map,表示当前括号内的元素和数量
2.初始化栈并添加一个栈顶
3.确定何时压入一个栈元素并相应操作:遇到'('压入一个新的map,表示这一个括号内的元素和数量
4.确定何时弹出一个栈元素并相应操作:遇到')'弹出这一个括号内的map,获取上一个括号内的map(即为top()),加上这一个括号内的元素下标系数乘以算得的括号系数
5.处理一个括号内的栈元素,大写字母+小写字母+小标系数=一个化学式,存入当map
6.最后栈顶元素为这一个方程式的map,但不包括前面的系数,所以结果map为栈顶的map乘上传入的前面系数
```
//提取一个的化学式的元素及系数(核心) 
map parseFormula(string s,int qianXi){
    map res;
    stack> st; 
    st.push(map());//先加一层栈顶 
    for(int i=0;i         if(s[i]=='('){
            //进入新的一层括号 
            st.push(map());
            i++;
        }
        else if(s[i]==')'){
            //提取一个层级的map,乘上括号后面的系数 
            i++;
            int kuohaoXi=parseNumber(s,i);//这个函数更改i,下面不用i++了 
            auto top_ele=st.top();//top_ele为map和类型 
            st.pop();//弹出这层,下面的 s.top()为上一层 
            for(auto &x:top_ele){//x为pair类型 
                st.top()[x.first]+=x.second*kuohaoXi;//改变上一层的,加上这一层的为这一层每个string的int(下标系数)乘上这一层的括号系数 
            }
        }
        else{//处理这一层括号内的单个元素 
            string ele; 
            ele+=s[i++];//提取大写字母
            while(i='a' && s[i]<='z'){
                //提取小写字母 
                ele+=s[i++];
            } 
            int xiaXi=parseNumber(s,i);//提取下标系数
            st.top()[ele]+=xiaXi; 
        }
    }
    //将栈顶的map乘上前面系数放到res的map里面 
    for(auto &x:st.top()){
        res[x.first]+=x.second*qianXi;
    }
    return res;
}

```

你可能感兴趣的:(CCF-CSP认证,算法,前端,c++)