[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.图 ...
随机推荐
- Java大数练习第二弹
hdu1250 水题 题目链接:pid=1250">http://acm.hdu.edu.cn/showproblem.php?pid=1250 import java.util.*; ...
- 还原对于server失败 备份集中的数据库备份与现有数据库不同
还原对于server失败 备份集中的数据库备份与现有数据库不同 今天在SQL Server 2008 R2中还原一个数据库备份,遇到错误.还原对于server失败 备份集中的数据库备份 ...
- U4699 鸡蛋
U4699 鸡蛋 0通过 37提交 题目提供者飞翔 标签 难度尚无评定 提交 最新讨论 暂时没有讨论 题目背景 调皮的kkk准备恶搞他的同学兼朋友——你! 题目描述 kkk准备从楼上扔鸡蛋下来砸在lz ...
- Data Url生成工具之HTML5 FileReader实现
百度经验版本号:怎样用HTML5的FileReader生成Data Url 上一篇讲了:用Visual Studio 2010编写Data Url生成工具C#版 今天用HTML5 FileReader ...
- 【Hnoi2010】Bzoj2002 Bounce & Codevs2333 弹飞绵羊
Position: http://www.lydsy.com/JudgeOnline/problem.php?id=3143 http://codevs.cn/problem/2333/ Descri ...
- bzoj4872
期望dp 首先如果k=n的话,那么我们从后往前,只要看到两者的灯就关上,因为如果当前一个灯没关上,那么之后不可能关上,一个灯只能由自己倍数控制,所以这样我们就计算出了需要操作的次数,如果这个次数< ...
- 用回调函数创建一个XMLHttpRequest,并从一个TXT文件中检索数据。
<script> var xmlhttp; function loadXMLDoc(url,soyo) { if (window.XMLHttpRequest) {// IE7+, Fir ...
- 基于Hive的手机应用信息统计分析系统
目录 项目概要 具体实现 HIVE查询 项目概要 需求 手机应用日志 定期离线分析手机应用新增用户.活跃用户.沉默用户.启动次数.版本分布和留存用户等业务指标. 工作流程 手机APP启动时,上报启动日 ...
- 红黑树插入操作原理及java实现
红黑树是一种二叉平衡查找树,每个结点上有一个存储位来表示结点的颜色,可以是RED或BLACK.红黑树具有以下性质: (1) 每个结点是红色或是黑色 (2) 根结点是黑色的 (3) 如果一个结点是红色的 ...
- MVVMLight消息通知实现机制详解(二)
接上文 MVVMLight消息通知实现机制详解(一) 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型.Key值.Action.Target(订阅对象本身) 在发生订阅事 ...