用于解决简单数学方程的数据结构

时间:2011-04-20 21:18:02

标签: c++

当接受表达式(10 + 5 * 15)并遵循操作顺序时。

如何最好地解决这样的问题?什么样的数据结构最好?

感谢。

6 个答案:

答案 0 :(得分:8)

我会和Dijkstra的Shunting yard algorithm一起创建AST

答案 1 :(得分:4)

尝试使用recursive descent解析表达式。这将为您提供一个尊重操作顺序的解析树。

答案 2 :(得分:2)

此任务的常用数据结构是堆栈。当你正在编写像编译这样的东西时,创建一个抽象语法树很有用,但是对于简单的评估,它通常是矫枉过正的。

答案 3 :(得分:1)

想一想 - 什么是运营商?几乎每个运算符(+, - ,*,/)都是二进制运算符。括号是深度构造函数;用括号移动一层更深。

事实上,构建解决此问题所需的数据将是您最大的障碍。

答案 4 :(得分:0)

它在Java中,但这似乎从中缀转换为后缀,然后使用基于堆栈的方法进行评估。它将数字放入堆栈,到达运算符,然后从堆栈中弹出两个数字,用运算符(x + / - )来计算它们。

http://enel.ucalgary.ca/People/Norman/enel315_winter1999/lab_solutions/lab5sol/exF/Calculator.java

转换如下:

  • 从左侧扫描中缀字符串 右。
  • 初始化空堆栈。
  • 如果扫描的字符是操作数,请将其添加到Postfix字符串。如果扫描的字符是操作符并且堆栈是空的
  • 将角色推到堆叠状态。
    • 如果扫描的字符是操作数且堆栈不为空,请将字符的优​​先级与堆栈顶部的元素(topStack)进行比较。如果topStack优先于扫描的字符,则弹出堆栈,否则将扫描的字符推送到堆栈。只要stack不为空且topStack优先于字符,就重复此步骤。
  • 重复此步骤,直到扫描完所有字符。 (扫描完所有字符后,我们必须添加堆栈可能具有的任何字符到Postfix字符串。)
  • 如果stack不为空,请将topStack添加到 Postfix字符串并弹出堆栈。 只要堆栈是,重复此步骤 不是空的。
  • 返回Postfix字符串。
  • 评估Postfix字符串。

答案 5 :(得分:0)

如果你需要简单地计算可用作字符串的表达式的结果,那么我根本就没有数据结构,只是函数如下:

//
// expression ::= addendum [ { "-" | "+" } addendum ]
// addendum ::= factor [ { "*" | "/" } factor ]
// factor ::= { number | sub-expression | "-" factor }
// sub-expression ::= "(" expression ")"
// number ::= digit [ digit ]
// digit ::= { "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" }
//

int calcExpression(const char *& p);
int calcDigit(const char *& p);
int calcNumber(const char *& p);
int calcFactor(const char *& p);
int calcAddendum(const char *& p);

其中每个函数只接受一个const char *的引用,它从中读取(递增指针)并返回结果的数值作为值,在出现问题时抛出异常。

此方法不需要任何数据结构,因为将C ++堆栈用于中间结果。举个例子......

int calcDigit(const char *& p)
{
    if (*p >= '0' && *p <= '9')
        return *p++ - '0';
    throw std::runtime_error("Digit expected");
}

int calcNumber(const char *& p)
{
    int acc = calcDigit(p);
    while (*p >= '0' && *p <= '9')
        acc = acc * 10 + calcDigit(p);
    return acc;
}

如果您需要编写将字符串(例如包括变量或函数调用)转换为代码或字节码的编译器,那么最好的解决方案可能是使用通用的n路树或具有特定结构的树来启动对于不同的AST节点类型。