[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.图 ...
随机推荐
- python基础练习-猜年龄、编写登陆接口小程序
python基础练习: 一.猜年龄 , 可以让用户最多猜三次! age=40 count = 1 while count <=3 : user_guess=int(input("i ...
- 关于Tomcat的点点滴滴(体系架构、处理http请求的过程、安装和配置、文件夹结构、设置压缩和对中文文件名称的支持、以及Catalina这个名字的由来……等)
总结Tomcat的体系架构.处理http请求的过程.安装和配置.文件夹结构.设置压缩和对中文文件名称的支持.以及Catalina这个名字的由来--等. Tomcat和JVM: 一个Tomcat仅仅会启 ...
- SmartSchool CC校友录V8(毕业入世版)
SmartSchool CC校友录V8(毕业入世版) 使用说明 CC校友录V8(毕业入世版) 主要面向毕业后在某城市工作的校友,给大家构建一个充分交流的平台,“人脉”积累是本软件的功能特色,为此淡化了 ...
- Linux 数据分析常用 shell命令
.文件合并 目录下有成千上万的小文件,需合并成大文件,直接cat 返回参数列表过长 ls |xargs -t -I{} cat {} >> merge.txt 2.从文本中截取行特定内容 ...
- 并发与并行(concurrency vs parallesim)
最近对计算机中并发(concurrency)和并行(parallesim)这两个词的区别很迷惑,将搜索到的相关内容整理如下. http://www.vaikan.com/docs/Concurrenc ...
- Uva 11151 - Longest Palindrome
A palindrome is a string that reads the same from the left as it does from the right. For example, I ...
- SEL是啥玩意
一.了解SEL前的准备-----isa指针简述 1.一个类就像一个 C 结构,NSObject 声明了一个成员变量: isa.由于 NSObject 是所有类的根类,所以所有的对象都会有一个 isa ...
- PCB CS架构(工程系统)实现单点登入方法
社会的不断进步发展,分工也越来越细了.而我们工作接触的范围也越来越狭小了,但这不是倒退了,而是分工之细让人们在各个方面深耕细作.PCB企业软件系统发展路线同样也如此,随着我们PCB企业发展不断壮大,软 ...
- Rails 拉数据初始数据库
rails c [1] pry(main)> Scraping.exec
- codevs1669 运输装备(背包dp)
1669 运输装备 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 德国放松对英国的进攻后,把矛头指向了东北——苏联 ...