[C++] 配平化学方程式算法的封装
有人已经实现了配平的方法,在此不再重复介绍。
但是,上述的方法所提供的代码还是存在着问题,需要进一步修改。
首先,因为 frac 这个结构的成员函数和其它操作函数已被声明并定义至一个单一的文件里,
因此,首先要将它的声明和定义分开来。把 frac 结构体抽离至封装的类以外,作为前置声明。
因为原代码是直接 printf() 输出的,而我们需要的是获取它输出的结果。
所以,改变它输出的位置,声明一个 string ,将配好以后的结果直接赋值到 string 里。
最终代码实现:
[C++ 源代码]
/* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
* (This file is the part of the ECPT Project)
* Author: Exzh_PMGI
* E-mail: realexzh@gmail.com
* License: LGPL v3.0 / Exzh Commerical License
* Copyright: (C) Exzh_PMGI
* Qt Framework 5.10 has been tested successfully
* If you want to use the code for business,
* please contact me by my email.
*/ #include "exequationbalancer.h" #include <QDebug> int gcd(int x, int y) {
return x % y == ? y : gcd(y, x%y);
} int lcm(int x, int y) {
return x * y / gcd(x, y);
} frac createFrac(int a, int b)
{
frac tmp = { a,b };
return tmp;
} frac Abs(frac x) {
int p = x.a> ? x.a : -x.a, q = x.b> ? x.b : -x.b;
return createFrac(p, q);
} string exEquationBalancer::getResult(string inputstr)
{
strcpy(s,inputstr.c_str());
int lst = ;
for (int i = ;i<strlen(s);i++) {
if (i == strlen(s) - )scan(lst, i);
if (s[i] == '+' || s[i] == '=')
{
scan(lst, i - );
lst = i + ;
}
if (s[i] == '=')flag = -; //等号后面的系数变负
}
if (Solve())
for (int i = ;i <= c2 - ;i++)
ans[i] = M[i][N + ];
else output+="No Solution";
int tmp = lcm(ans[].b, ans[].b);
for (int i = ;i <= c2;i++)tmp = lcm(tmp, ans[i].b);
for (int i = ;i <= c2;i++)Ans[i] = ans[i].a*tmp / ans[i].b; //取分母Lcm,把分数变整数
for (int i = ;i <= c2;i++)
{
if (Ans[i]>) output+=to_string(Ans[i]);
for (int j = ;j<strlen(mat[i]);j++)
output+=mat[i][j];
if (i == c2)
{
return output;
qDebug()<<QString::fromStdString(output);
}
else if (i == c1) output+="=";
else output+="+";
}
} bool exEquationBalancer::Solve() { //解方程 (矩阵 高cnt,宽c2+1,c2+1列常数全0)
ans[c2] = ; //令最后一个解为1
for (int i = ;i <= cnt;i++) {
for (int j = ;j <= c2;j++)
M[i][j] = fun[i][j];
}
for (int i = ;i <= cnt;i++)
M[i][c2].a = -M[i][c2].a; //移到常数
//高斯消元过程
N = c2 - , K = cnt;
for (int k = ;k <= N;k++) {
frac maxm = createFrac(-, );
int maxi;
for (int i = k;i <= K;i++)
if (maxm<Abs(M[i][k]))
maxm = Abs(M[i][k]), maxi = i;
if (maxm == createFrac(, ))
return false;
if (maxi != k)
for (int j = ;j <= N + ;j++) {
swap(M[k][j], M[maxi][j]);
}
frac tmp = M[k][k];
for (int j = ;j <= N + ;j++)
M[k][j] = M[k][j] / tmp;
for (int i = k - ? : ;i <= K;i++) {
if (i == k)continue;
frac tmp = M[i][k];
for (int j = ;j <= N + ;j++)
M[i][j] = M[i][j] - tmp * M[k][j];
}
}
return true;
} void exEquationBalancer::scan(int l, int r) { //处理物质
c2++;
for (int i = ;i <= r - l;i++)mat[c2][i] = s[l + i]; //存下元素的名字
if (flag == )c1++; //统计一下反应物数量
int tmp = ; //tmp是小括号倍数
for (int i = l;i <= r;i++) {
if (s[i] == ')')tmp = ;
if (s[i] == '(') {
int j = i + ;while (s[j] != ')')j++; //找这个括号的范围
tmp = getint(j); //读")"右边的数字
}
if (s[i] >= 'A'&&s[i] <= 'Z') { //发现元素
int x = s[i] - 'A' + , y = ;
if (s[i + ] >= 'a'&&s[i] <= 'z') //看一眼是一个字母的还是两个的
y = s[i + ] - 'a' + ;
if (!Map[x][y])Map[x][y] = ++cnt; //判重
fun[Map[x][y]][c2] += flag * getint(i)*tmp; //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2)
}
}
} int exEquationBalancer::getint(int pos) { //读数
pos++;
if (s[pos] >= 'a'&&s[pos] <= 'z')pos++;
if (s[pos]<'' || s[pos]>'')return ; //没数就是1
else {
int x = ;
while (s[pos] >= ''&&s[pos] <= '')x = x * + s[pos] - '', pos++; //读元素后面的数字
return x;
}
} void exEquationBalancer::print() {
output += to_string(N);
output += " ";
output += to_string(K);
output += "\n";
for (int i = ;i <= K;i++) {
for (int j = ;j <= N + ;j++)
{
output += to_string(M[i][j].a);
output += " ";
}
output += "\n";
}
output += "\n";
}
[C++ 头文件]
/* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
* (This file is the part of the ECPT Project)
* Author: Exzh_PMGI
* E-mail: realexzh@gmail.com
* License: LGPL v3.0 / Exzh Commerical License
* Copyright: (C) Exzh_PMGI
* Qt Framework 5.10 has been tested successfully
* If you want to use the code for business,
* please contact me by my email.
*/ #ifndef EXEQUATIONBALANCER_H
#define EXEQUATIONBALANCER_H #include <string>
#include "../exstdc++.h" using namespace std;
static string output;
int lcm(int x, int y);
int gcd(int x, int y); struct frac { //分数类
int a, b;
void reduce() {
int x = gcd(a, b);
a /= x, b /= x;
}
frac createFrac(int a, int b)
{
frac tmp = { a,b };
return tmp;
}
frac operator = (int x) {
a = x, b = ;
return *this;
}
frac operator = (const frac x) {
a = x.a, b = x.b;
reduce();
return *this;
}
frac operator + (const frac x) {
return createFrac(b*x.a + a * x.b, b*x.b);
}
frac operator - (const frac x) {
return createFrac(a*x.b - b * x.a, b*x.b);
}
frac operator * (const frac x) {
return createFrac(a*x.a, b*x.b);
}
frac operator / (const frac x) {
return createFrac(a*x.b, b*x.a);
}
bool operator < (const frac x) {
return a * x.b<b*x.a;
}
bool operator == (const frac x) {
return a * x.b == b * x.a;
}
void print() {
if (b == )
{
output += to_string(a);
output += "\n";
}
else
{
output += to_string(a);
output += "/";
output += to_string(b);
}
}
}; frac createFrac(int a, int b);
frac Abs(frac x); class exEquationBalancer
{
public:
string getResult(string inputstr); private:
bool Solve();
void scan(int l, int r);
int getint(int pos);
void print(); char s[];
int fun[][];
int Map[][]; //手动MAP
frac M[][]; //求解矩阵
frac ans[]; //解
int Ans[]; //整数解
int cnt, c1, c2, flag = , N, K; //cnt数元素,c1数反应物,c2总数 (未知数的数量)
char mat[][]; //存储物质的名称
}; #endif // EXEQUATIONBALANCER_H
[C++] 配平化学方程式算法的封装的更多相关文章
- 配平化学方程式的C++代码实现
配平化学方程式的C++代码实现 纪念一下我今天写过了 20171006. (去年的这个时候我就有了这个大胆的想法, 当时的思路是:字符串处理->暴力搜系数,可是太年轻写不对,我那会还是个只会模拟 ...
- Python趣用—配平化学方程式
不知不觉已经毕业多年了,不知道大家是否还记得怎么配平化学方程式呢?反正小编我是已经记不太清了,所以今天的文章除了分享如何用python配平化学方程式,顺带着还会复习 一些化学方程式的知识,希望广大化学 ...
- 用c++后缀自动机实现最大公共字符串算法,并封装成Python库
后缀自动机的C++代码转自https://e-maxx.ru/algo/suffix_automata,其余封装为自写. 在C++文件同级目录建立setup.py文件,代码如下: # !/usr/bi ...
- 【HiJ1m】在NOIP2017前写过的有用的东西汇总
http://www.cnblogs.com/Elfish/p/7544623.html 高级树状数组 http://www.cnblogs.com/Elfish/p/7554420.html BST ...
- CCF-CSP题解 201912-3 化学方程式
判断化学方程式是否配平. 字符串处理. 有点编译原理递归下降法的感觉. 考场源码,比较粗糙. // INFO BEGIN // // User = 201911513451(陶杨) // Group ...
- 1.K近邻算法
(一)K近邻算法基础 K近邻(KNN)算法优点 思想极度简单 应用数学知识少(近乎为0) 效果好 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 图解K近邻算法 上图是以 ...
- scikit-learn 支持向量机算法库使用小结
之前通过一个系列对支持向量机(以下简称SVM)算法的原理做了一个总结,本文从实践的角度对scikit-learn SVM算法库的使用做一个小结.scikit-learn SVM算法库封装了libsvm ...
- Android 设计模式实战之关于封装计费代码库的策略模式详谈
写在之前 这周生活上出现了很多的不如意,从周一开始就觉得哪里出现了问题,然后就是各种烦躁的情绪,后来事情还真是如预感的那样发生了,很是心痛,但也无可奈何,希望大家都好好珍惜自己身边的人:友人,亲人,家 ...
- 6种基础排序算法java源码+图文解析[面试宝典]
一.概述 作为一个合格的程序员,算法是必备技能,特此总结6大基础算法.java版强烈推荐<算法第四版>非常适合入手,所有算法网上可以找到源码下载. PS:本文讲解算法分三步:1.思想2.图 ...
随机推荐
- Hibernate基于注解的双向one-to-many映射关系的实现
在项目中用到了一对多的实体类关系映射,之前接触的都是基于配置文件的映射实现.可是公司的大部分都是基于注解的.因此自己參考之前的代码捣鼓了基于注解的一对多的映射关系实现. 背景: 一的一端:QingAo ...
- 修改Cygwin的默认启动目录
安装Cygwin后发现Cygwin默认的用户主目录是Windows的用户主目录(一般为:C:\Users\[UserName]\),要想修改为cygwin安装目录下的home\[UserName]\可 ...
- Flash--元件和实例
1.元件简述: 元件在Flash影片中是一种特殊的对象.在Flash中仅仅须要创建一次,然后能够在整部电影中重复使用而不会显著添加 文件大小. 事实上在使用元件时,我们一般使用的是该元件的实例,所以说 ...
- elasticsearch 布尔过滤器 游标查询 Scroll
组合过滤器 | Elasticsearch: 权威指南 | Elastic https://www.elastic.co/guide/cn/elasticsearch/guide/current/co ...
- Luogu3403跳楼机
https://zybuluo.com/ysner/note/1099616 题面 给你三个数\(x\),\(y\),\(z\),问你能够凑出多少个[1,\(h\)]之间的数. 解析 处理出\(y\) ...
- JS/CSS 压缩的好处
1.减小了文件的体积 2.减小了网络传输量和带宽占用 3.减小了服务器的处理的压力 4.提高了页面的渲染显示的速度
- canvas做的时钟,学习下
canvas标签只是图形容器,您必须使用脚本来绘制图形. getContext() 方法可返回一个对象,该对象提供了用于在画布上绘图的方法和属性.——获取上下文对象. getContext(" ...
- mybatis多个参数查询问题
一.话不多数,错误如下 Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException ...
- ACM_ZHANGZHANG喜欢手表
ZHANGZHANG喜欢手表 Time Limit: 2000/1000ms (Java/Others) Problem Description: ZHANGZHANG刚过生日,收到了好朋友NENGN ...
- html表单——使用frameset写一个导航栏效果
主页面: <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4 ...