[C++] 配平化学方程式算法的封装

有人已经实现了配平的方法,在此不再重复介绍。

https://www.cnblogs.com/Elfish/p/7631603.html

但是,上述的方法所提供的代码还是存在着问题,需要进一步修改。

 

首先,因为 frac 这个结构的成员函数和其它操作函数已被声明并定义至一个单一的文件里,

因此,首先要将它的声明和定义分开来。把 frac 结构体抽离至封装的类以外,作为前置声明。

因为原代码是直接 printf() 输出的,而我们需要的是获取它输出的结果。

所以,改变它输出的位置,声明一个 string ,将配好以后的结果直接赋值到 string 里。

 

最终代码实现:

[C++ 源代码]

  1 /* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
  2  * (This file is the part of the ECPT Project)
  3  * Author: Exzh_PMGI
  4  * E-mail: realexzh@gmail.com
  5  * License: LGPL v3.0 / Exzh Commerical License
  6  * Copyright: (C) Exzh_PMGI
  7  * Qt Framework 5.10 has been tested successfully
  8  * If you want to use the code for business,
  9  * please contact me by my email.
 10  */
 11 
 12 #include "exequationbalancer.h"
 13 
 14 #include <QDebug>
 15 
 16 int gcd(int x, int y) {
 17     return x % y == 0 ? y : gcd(y, x%y);
 18 }
 19 
 20 int lcm(int x, int y) {
 21     return x * y / gcd(x, y);
 22 }
 23 
 24 frac createFrac(int a, int b)
 25 {
 26     frac tmp = { a,b };
 27     return tmp;
 28 }
 29 
 30 frac Abs(frac x) {
 31     int p = x.a>0 ? x.a : -x.a, q = x.b>0 ? x.b : -x.b;
 32     return createFrac(p, q);
 33 }
 34 
 35 string exEquationBalancer::getResult(string inputstr)
 36 {
 37     strcpy(s,inputstr.c_str());
 38     int lst = 0;
 39     for (int i = 1;i<strlen(s);i++) {
 40         if (i == strlen(s) - 1)scan(lst, i);
 41         if (s[i] == '+' || s[i] == '=')
 42         {
 43             scan(lst, i - 1);
 44             lst = i + 1;
 45         }
 46         if (s[i] == '=')flag = -1;                            //等号后面的系数变负
 47     }
 48     if (Solve())
 49         for (int i = 1;i <= c2 - 1;i++)
 50             ans[i] = M[i][N + 1];
 51     else output+="No Solution";
 52     int tmp = lcm(ans[1].b, ans[2].b);
 53     for (int i = 3;i <= c2;i++)tmp = lcm(tmp, ans[i].b);
 54     for (int i = 1;i <= c2;i++)Ans[i] = ans[i].a*tmp / ans[i].b;    //取分母Lcm,把分数变整数
 55     for (int i = 1;i <= c2;i++)
 56     {
 57         if (Ans[i]>1) output+=to_string(Ans[i]);
 58         for (int j = 0;j<strlen(mat[i]);j++)
 59             output+=mat[i][j];
 60         if (i == c2)
 61         {
 62             return output;
 63             qDebug()<<QString::fromStdString(output);
 64         }
 65         else if (i == c1) output+="=";
 66         else output+="+";
 67     }
 68 }
 69 
 70 bool exEquationBalancer::Solve() {                    //解方程  (矩阵 高cnt,宽c2+1,c2+1列常数全0)
 71     ans[c2] = 1;                                    //令最后一个解为1
 72     for (int i = 1;i <= cnt;i++) {
 73         for (int j = 1;j <= c2;j++)
 74             M[i][j] = fun[i][j];
 75     }
 76     for (int i = 1;i <= cnt;i++)
 77         M[i][c2].a = -M[i][c2].a;            //移到常数
 78                                              //高斯消元过程
 79     N = c2 - 1, K = cnt;
 80     for (int k = 1;k <= N;k++) {
 81         frac maxm = createFrac(-1, 1);
 82         int maxi;
 83         for (int i = k;i <= K;i++)
 84             if (maxm<Abs(M[i][k]))
 85                 maxm = Abs(M[i][k]), maxi = i;
 86         if (maxm == createFrac(0, 1))
 87             return false;
 88         if (maxi != k)
 89             for (int j = 1;j <= N + 1;j++) {
 90                 swap(M[k][j], M[maxi][j]);
 91             }
 92         frac tmp = M[k][k];
 93         for (int j = 1;j <= N + 1;j++)
 94             M[k][j] = M[k][j] / tmp;
 95         for (int i = k - 1 ? 1 : 2;i <= K;i++) {
 96             if (i == k)continue;
 97             frac tmp = M[i][k];
 98             for (int j = 1;j <= N + 1;j++)
 99                 M[i][j] = M[i][j] - tmp * M[k][j];
100         }
101     }
102     return true;
103 }
104 
105 void exEquationBalancer::scan(int l, int r) {             //处理物质
106     c2++;
107     for (int i = 0;i <= r - l;i++)mat[c2][i] = s[l + i];        //存下元素的名字
108     if (flag == 1)c1++;                                //统计一下反应物数量
109     int tmp = 1;                                        //tmp是小括号倍数
110     for (int i = l;i <= r;i++) {
111         if (s[i] == ')')tmp = 1;
112         if (s[i] == '(') {
113             int j = i + 1;while (s[j] != ')')j++;            //找这个括号的范围
114             tmp = getint(j);                            //读")"右边的数字
115         }
116         if (s[i] >= 'A'&&s[i] <= 'Z') {                    //发现元素
117             int x = s[i] - 'A' + 1, y = 0;
118             if (s[i + 1] >= 'a'&&s[i] <= 'z')                //看一眼是一个字母的还是两个的
119                 y = s[i + 1] - 'a' + 1;
120             if (!Map[x][y])Map[x][y] = ++cnt;            //判重
121             fun[Map[x][y]][c2] += flag * getint(i)*tmp;    //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2)
122         }
123     }
124 }
125 
126 int exEquationBalancer::getint(int pos) {                //读数
127     pos++;
128     if (s[pos] >= 'a'&&s[pos] <= 'z')pos++;
129     if (s[pos]<'0' || s[pos]>'9')return 1;                                //没数就是1
130     else {
131         int x = 0;
132         while (s[pos] >= '0'&&s[pos] <= '9')x = x * 10 + s[pos] - '0', pos++;        //读元素后面的数字
133         return x;
134     }
135 }
136 
137 void exEquationBalancer::print() {
138     output += to_string(N);
139     output += " ";
140     output += to_string(K);
141     output += "\n";
142     for (int i = 1;i <= K;i++) {
143         for (int j = 1;j <= N + 1;j++)
144         {
145             output += to_string(M[i][j].a);
146             output += " ";
147         }
148         output += "\n";
149     }
150     output += "\n";
151 }

 

[C++ 头文件]

  1 /* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
  2  * (This file is the part of the ECPT Project)
  3  * Author: Exzh_PMGI
  4  * E-mail: realexzh@gmail.com
  5  * License: LGPL v3.0 / Exzh Commerical License
  6  * Copyright: (C) Exzh_PMGI
  7  * Qt Framework 5.10 has been tested successfully
  8  * If you want to use the code for business,
  9  * please contact me by my email.
 10  */
 11 
 12 #ifndef EXEQUATIONBALANCER_H
 13 #define EXEQUATIONBALANCER_H
 14 
 15 #include <string>
 16 #include "../exstdc++.h"
 17 
 18 using namespace std;
 19 static string output;
 20 int lcm(int x, int y);
 21 int gcd(int x, int y);
 22 
 23 struct frac {                            //分数类
 24         int a, b;
 25         void reduce() {
 26                 int x = gcd(a, b);
 27                 a /= x, b /= x;
 28         }
 29         frac createFrac(int a, int b)
 30         {
 31                 frac tmp = { a,b };
 32                 return tmp;
 33         }
 34         frac operator = (int x) {
 35                 a = x, b = 1;
 36                 return *this;
 37         }
 38         frac operator = (const frac x) {
 39                 a = x.a, b = x.b;
 40                 reduce();
 41                 return *this;
 42         }
 43         frac operator + (const frac x) {
 44                 return createFrac(b*x.a + a * x.b, b*x.b);
 45         }
 46         frac operator - (const frac x) {
 47                 return createFrac(a*x.b - b * x.a, b*x.b);
 48         }
 49         frac operator * (const frac x) {
 50                 return createFrac(a*x.a, b*x.b);
 51         }
 52         frac operator / (const frac x) {
 53                 return createFrac(a*x.b, b*x.a);
 54         }
 55         bool operator < (const frac x) {
 56                 return a * x.b<b*x.a;
 57         }
 58         bool operator == (const frac x) {
 59                 return a * x.b == b * x.a;
 60         }
 61         void print() {
 62                 if (b == 1)
 63                 {
 64                         output += to_string(a);
 65                         output += "\n";
 66                 }
 67                 else
 68                 {
 69                         output += to_string(a);
 70                         output += "/";
 71                         output += to_string(b);
 72                 }
 73         }
 74 };
 75 
 76 frac createFrac(int a, int b);
 77 frac Abs(frac x);
 78 
 79 class exEquationBalancer
 80 {
 81 public:
 82     string getResult(string inputstr);
 83 
 84 private:
 85     bool Solve();
 86     void scan(int l, int r);
 87     int getint(int pos);
 88     void print();
 89 
 90     char s[55];
 91     int fun[55][55];
 92     int Map[27][27];                        //手动MAP
 93     frac M[55][55];                            //求解矩阵
 94     frac ans[55];                            //
 95     int Ans[55];                            //整数解
 96     int cnt, c1, c2, flag = 1, N, K;                //cnt数元素,c1数反应物,c2总数 (未知数的数量)
 97     char mat[55][55];                        //存储物质的名称
 98 };
 99 
100 #endif // EXEQUATIONBALANCER_H

 

转载于:https://www.cnblogs.com/exzhpmgi/p/10089242.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值