Algorithm 求解以字符串表示的线性方程组

Algorithm 求解以字符串表示的线性方程组,algorithm,expression-trees,Algorithm,Expression Trees,我得到一个字符串2*x+5-(3*x-2)=x+5,我需要求解x。我的思维过程是把它转换成表达式树,比如 = / \ - + /\ /\ + - x 5 /\ /\ * 5 * 2 /\ /\ 2 x 3 x 但是我如何从这里减少树的数量呢?还有其他想法吗 你必须用代数中的公理来简化它 a * (b + c) -> (a * b) + (a * c) 这是通过

我得到一个字符串
2*x+5-(3*x-2)=x+5
,我需要求解
x
。我的思维过程是把它转换成表达式树,比如

          =
        /  \
       -    +
      /\    /\
     +  -   x  5
    /\  /\ 
   *  5 * 2
  /\   /\
 2  x  3 x

但是我如何从这里减少树的数量呢?还有其他想法吗

你必须用代数中的公理来简化它

a * (b + c) -> (a * b) + (a * c)
这是通过检查过程树中每个节点的类型来完成的。一旦事物完全扩展成术语,你就可以检查它们是否是线性的,等等

树中的值将是变量或数字。然而,将这些表示为从某个AbstractTreeNode类继承的类并不十分简洁,因为CPluPlus没有多个分派。因此,最好用“c”的方式

enum NodeType {
    Number,
    Variable,
    Addition //to represent the + and *
}

struct Node {
    NodeType type;
    //union {char*,  int, Node*[2]} //psuedo code, but you need
    //something kind of like this for the 
    //variable name ("x") and numerical value
    //and the children
}
现在,您可以使用switch case查询节点及其子节点的类型

正如我前面所说的,C++惯用代码使用虚拟函数,但缺少必要的多个调度来解决这个问题。(无论如何,您都需要存储该类型)

然后你把这些项分组,然后解方程

例如,您可以使用规则规范化树

constant + variable -> variable + constant
将x始终放在术语的左边。然后,
x*2+x*4
可以更容易地简化

var * constant + var * constant -> (sum of constants) * var
在你的例子中

首先,通过移动术语简化“=”(按照上面的规则)

右手边将是-1*(x+5),变成-1*x+-1*5。左手边会更难-考虑用-+1*B/< P>替换-B。 最后,

2x+5+-3x+2+-x+-5=0

然后,您可以根据需要将术语分组。(通过扫描等方式)

(2+-3+-1)x+5+2+-5=0


把它们加起来,当你有mx+c时,求解它。

假设你有一个一阶方程,检查两边的所有叶子。在每一侧,有两个箱子:一个用来将包含X的倍数的所有叶子相加,另一个用来将包含常数的倍数的所有叶子相加。当你沿着树叶上的每一根树枝爬上树时,要么把每一个木箱都加上,要么把每一个木箱都乘上。你最终会得到一些概念上类似的东西

a*x + b = c*x + d
在这一点上,你可以解决

x = (d - b) / (a - c)

假设方程可以简化为f(x)=0,f(x)=a*x+b

您可以将表达式树中的所有叶子转换为f(x),例如:2->0*x+2,3*x->3*x+0,然后您可以在表达式树中对f(x)进行算术运算。最后解方程f(x)=0


如果函数比多项式复杂得多,则可以在C++上进行二值搜索,并用表达式树计算方程的左右两边。根据您实际使用的语言,解决方案很可能会有很大的不同。或者,最好是c++@PAURR不是真正的模式匹配,与其他方法相比会有所不同,但概念是相同的same@user3125280“我不认为这是一个具体的解决类型问题”-那么它不应该有或标签。它非常受欢迎,可以独立使用,但也可能适用。对于非语言特定的问题,或可以使用,但我认为这两种问题在这里都不特别适用。您能解释一下在我指定的示例中它是如何发生的吗?@Aks这有帮助吗?例如,如果我们已经这样做了,将一阶逻辑公式简化为子句范式,这是一个非常相似的过程。我能让它变得更有用吗?是的,我知道这些公理将如何应用到树上,但我怀疑我到底会怎么做that@Aks我真的没有时间为你做这件事。不过我会添加一些代码:)@Aks如果问题是关于上述树的实际实现,那么应该将其标记为c/c++。如果是这样,请更改问题以反映这一点-哦,我的观点是分派的东西,请忽略这一部分。我在想,我会对表达式树进行后序遍历,对于遇到的每个x,如果父操作符是a*,则将另一个叶存储为x的计数,否则将1存储为x的计数。这有意义吗?这很有意义。如果两片叶子都是常数,那么也要确保增加常数项。