【发布时间】:2013-12-03 12:59:25
【问题描述】:
我完全被我的一项任务困住了,需要一些帮助。
我们正在实现一个树类,它存储和评估二进制表达式。这是一个这样的表达式的示例:(MAJ (AND 3 4) (OR 1 2 3) (NOT 5) 4 )。这是指这棵树:
树以 LCRS 表示形式提供给我们,我们正在构建一个类来对其执行各种操作,例如查找树中的最大数、查找特定运算符的编号或打印原始导致给定树的公式。我已经弄清楚了所有这些,通过数小时的头疼和用于追踪大型递归函数的成堆纸张。
但我不知道最后一个需要的函数是
bool evaluate(const vector<bool> &values, Tree_Node* p)
此函数使用 bool 向量提供的真值计算表达式(例如,如果 values[3] 和 values[4] 都为真,则 (AND 3 4) 为真)。我花了很多时间寻找答案,并认为我对表达式树有所了解,但找不到任何关于它在 LCRS 表示中如何工作的信息。
我只是无法弄清楚递归。我把它分成了所有可能的情况,但是当你考虑到不同的运营商时,会有很多情况。为了保持简洁,我会说我的主要问题是:
如何评估每个子树?例如,在 LCRS 树中,
AND
/
3
\
4
我看到我需要回到 4,意识到这是最简单的(基本)情况,然后开始递归回到 AND,但是当我回来时我不知道如何获得正确的值到 AND。我需要一个额外的参数还是什么?也许传递操作,或者使用某种后续的额外指针?
//一些澄清的东西
四个运算符是:
- MAJ - 如果大多数输入为真,则返回真
- AND - 逻辑与(如果两个输入都为真,则为真)
- OR - 逻辑或
- NOT - 否定
(假设 SO 上的人理解 and,or,¬。)
Node 结构是一个典型的结构:
struct Tree_Node {
std::string data;
Tree_Node* left_child;
Tree_Node* right_sibling;
}
除了分配的附加功能外,Tree 类也是标准的, 如有必要,我可以发布代码,但它具有您期望的树的操作,并且可以正确编译和测试,问题仅与此功能有关。
我在这个和我的其他家庭作业之间敲打我的桌子......哦,CS专业的生活。任何帮助,一如既往,非常感谢。
编辑:
非常感谢所有帮助过我的人。我在这里得到的所有答案确实帮助我弄清楚了事情。有时它有助于获得一个新的视角。另外, std::pair 对我来说是新的!有趣的是,因为我有一个自己的模板类,它做同样的事情......猜猜是时候让那个家伙退休了!
等我完成作业后,我会把我的功能和分析贴在这里,以备日后参考。
编辑:
正如所承诺的,完成的功能。 count_children 在功能上与 rici 制定的 count 函数相同,而 TruthValues 是一个 std::pair 整数,如 Counts。再次感谢那些帮助我解决这个问题的人。当给定一个字符串(例如switch_help("MAJORITY") == 2)时,函数 switch_help 会为 switch 语句返回适当的数字。
bool BooleanFormula::evaluate(const vector<bool> & values, Tree_Node* p){
TruthValues truth_vals = TruthValues(0,0);
int control = switch_help(p->data);
switch (control){
case 1: //p->data = "MAJORITY"
truth_vals = count_children(values, p->left_child);
return (truth_vals.first > truth_vals.second);
//return true if there are more trues than falses
case 2: //p->data = "AND"
truth_vals = count_children(values, p->left_child);
return (truth_vals.second == 0);
//return true if there are no falses
case 3: //p->data = "OR"
truth_vals = count_children(values, p->left_child);
return (truth_vals.first >= 1);
//return true if there is at least one true
case 4: //p->data = "NOT"
return !(evaluate(values, p->left_child));
//return the inverse of what is obtained by evaluating the subtree
default: //p->data = some number
//in this case, we're just at a node with an index in it
return values[atoi((p->data).c_str())];
}
}
【问题讨论】:
-
提示:递归评估函数的结果应该是一个值列表,而不是(必然)单个值。
-
好吧,它最终必须返回一个布尔值,尽管我明白你在说什么。我一直在玩弄这个想法——如果我能得到一个向量或包含 3 和 4 的东西,我想这会很有帮助。如果我要添加某种列表作为函数的参数,并通过引用传递它,那么...我可以在到达底部时添加值并在备份的路上构建该列表?这可能行得通,但我会遇到多个递归调用查看同一个列表的问题吗?
-
顶级函数调用根上的递归 case,断言返回列表仅包含一个元素,并将其返回。其他一切都返回一个列表。它不会通过引用传入列表。您可以在之后进行一些优化,但首先要让它发挥作用。
-
从实现叶子案例开始,然后逐步向上。并遵循@Sneftel 的建议。
-
对不起,我还是有点糊涂。你是说我应该编写一个返回列表的辅助函数(或者对于不同的运算符可能不止一个)?那么,当原始函数具有完整的列表时,只有一个元素,可以返回该列表中的一个值吗?
标签: c++ algorithm recursion tree