Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 左子表达式树、右同级表达式树_C++_Algorithm_Recursion_Tree - Fatal编程技术网

C++ 左子表达式树、右同级表达式树

C++ 左子表达式树、右同级表达式树,c++,algorithm,recursion,tree,C++,Algorithm,Recursion,Tree,我完全被一项任务困住了,需要一些帮助 我们正在实现一个树类,它存储并计算一个二进制表达式。下面是这样一个表达的例子:(MAJ(和34)(或1234)(不是5)4)。这指的是这棵树: 树是在LCRS表示中提供给我们的,我们正在构建一个类来对它执行各种操作,例如查找树中的最大数、查找特定运算符的数,或者打印生成给定树的原始公式。通过几个小时的挠头和一堆用来跟踪大型递归函数的纸,我已经弄明白了所有这些 但我无法找出最后一个必需的函数,即 bool evaluate(const vector<b

我完全被一项任务困住了,需要一些帮助

我们正在实现一个树类,它存储并计算一个二进制表达式。下面是这样一个表达的例子:(MAJ(和34)(或1234)(不是5)4)。这指的是这棵树:

树是在LCRS表示中提供给我们的,我们正在构建一个类来对它执行各种操作,例如查找树中的最大数、查找特定运算符的数,或者打印生成给定树的原始公式。通过几个小时的挠头和一堆用来跟踪大型递归函数的纸,我已经弄明白了所有这些

但我无法找出最后一个必需的函数,即

bool evaluate(const vector<bool> &values, Tree_Node* p)
我知道我需要深入到4,意识到这是最简单的(基本)情况,然后开始递归到and,但我不知道如何在返回and时获得正确的值。我需要一个额外的参数还是什么?也许传递操作,或者使用某种额外的指针

//一些澄清材料

这四家运营商是:

  • MAJ-如果大多数输入为真,则返回真
  • AND-逻辑AND(如果两个输入均为真,则为真)
  • 或-逻辑或
  • 非-否定
(假设上面的人如此理解和/或不理解。)

节点结构是一种典型的结构:

struct Tree_Node {  
    std::string data;
    Tree_Node* left_child;
    Tree_Node* right_sibling;
}
树类也是标准的,除了用于赋值的附加函数, 如果需要,我可以发布代码,但它具有您期望的树操作,并且可以正确编译和测试,问题只是关于这个函数

我在这和其他作业之间把头撞在桌子上。。。哦,CS专业的生活。一如既往,我们非常感谢您的任何帮助

编辑:

非常感谢所有帮助我的人。我在这里得到的所有答案真的帮助我解决了问题。有时有助于获得新的视角。另外,std::pair对我来说是新的!有趣的是,因为我有一个自己的模板类,做同样的事情。。。我猜是时候让那个家伙退休了

当我完成作业后,我将在这里发布我的函数和分析,以供将来参考

编辑: 正如承诺的那样,完成的功能。count_children在功能上与rici设置的count函数相同,TruthValues是一个std::int对,与Counts类似。再次感谢那些帮助我解决这个问题的人。当给定一个字符串时,函数switch\u help为switch语句返回适当的数字(例如
switch\u help(“多数”)==2

bool BooleanFormula::evaluate(常量向量和值,树节点*p){
真值真值=真值(0,0);
int control=开关帮助(p->data);
开关(控制){
案例1://p->data=“多数”
真值=计数子项(值,p->左子项);
返回(真值第一>真值第二);
//如果真多于假,则返回真
案例2://p->data=“和”
真值=计数子项(值,p->左子项);
返回值(真值秒=0);
//如果没有错误,则返回true
案例3://p->data=“或”
真值=计数子项(值,p->左子项);
返回(真值第一次>=1);
//如果至少有一个true,则返回true
案例4://p->data=“不”
返回!(计算(值,p->左_子项));
//返回通过计算子树得到的结果的倒数
默认值://p->data=一些数字
//在这种情况下,我们只是在一个包含索引的节点上
返回值[atoi((p->data).c_str())];
}
}

如果我理解结构,在每个子树上,操作符位于根,第一个操作数作为根的左子级,后续操作数作为根的右链接 第一个操作数,对吗

然后,总体评估方案如下所示:

bool evaluate(const vector<bool> &values, Tree_Node* p) {
    bool result; 
    switch (p->op) {
        case BASE:
            return values[p->index];
        ...
        case AND:
            result = true;
            for (op = p->left; op != nullptr; op = op->right)
               result &= evaluate (values, op);
            return result;
        ...
    }
}
bool求值(常量向量和值,树节点*p){
布尔结果;
开关(p->op){
案例库:
返回值[p->index];
...
案例和:
结果=真;
对于(op=p->left;op!=nullptr;op=op->right)
结果&=评估(值,op);
返回结果;
...
}
}

(这里我假设叶子包含
值数组中的索引。

表达式树的递归计算涉及:

  • 评估树的每个节点
这反过来又要求:

  • 将操作应用于子对象(操作数)列表
现在,让我们尝试稍微系统化。考虑一下你的操作-<代码>不< /COD>,<代码>和,<代码>或和<代码> MaG/<代码>,并考虑如何在操作列表中计算每一个的值。具体来说,我们需要知道列表的内容吗?在所有情况下,以下两个数据都足够了。(只有一种情况下,两者都是必要的):

  • 列表中有多少值是
    TRUE

  • 列表的值中有多少是
    FALSE

(或者,第二个可能是“列表中有多少个值?”,这显然是等效的。)

如果
FALSE
子项的数量为0,
TRUE
子项的数量为0;
FALSE
子项的数量为
TRUE
子项的数量大于
FALSE
子项的数量,
MAJ
TRUE
子项的数量。(对于操作数列表,
NOT
至少有两种泛化,或者您可以将其限制为
TRUE
子级数为0,而
FALSEbool 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())];
    }

}
bool evaluate(const vector<bool> &values, Tree_Node* p) {
    bool result; 
    switch (p->op) {
        case BASE:
            return values[p->index];
        ...
        case AND:
            result = true;
            for (op = p->left; op != nullptr; op = op->right)
               result &= evaluate (values, op);
            return result;
        ...
    }
}
typedef std::pair<int, int> Counts;

Counts count(Tree_Node* node) {
  if (!node) return Counts{0, 0};
  Counts rest = count(node->right_sibling);
  if (evaluate(node))
    return Counts{rest.first + 1, rest.second};
  else
    return Counts{rest.first, rest.second + 1};
}
typedef std::pair<int, int> Counts;
Counts operator+(const Counts& a, const Counts& b) {
  return {a.first + b.first, a.second + b.second};
}

Counts count(Tree_Node* node) {
  if (!node)
    return Counts{0, 0};
  else
    return evaluate(node) + count(node->right_sibling);
}