如何使用树c ++评估布尔语句

时间:2012-01-18 22:05:33

标签: c++ tree

我有(x1 & x2) || (x3 || !x4)之类的陈述。 我会把这个陈述变成一棵树。 问题是如何生成truefalse值到x变量并获取此语句的所有输出?

我们有*T作为树根和所有树函数。也就是将树定义为链表树。

3 个答案:

答案 0 :(得分:1)

你是不是喜欢这样的?根据您实际创建和操作树的方式,您可能希望查看内存管理;这个例子很简陋。您还可能希望为输出添加调试标志。

#include <string>
#include <vector>
#include <iostream>

class Variable
{
public:
     Variable(const std::string& name = "Un-named", bool value = false)
         : name_(name)
     {}
     void setValue(bool val)
     {
         value_ = val;
     }
     bool getValue() const
     {
         return value_;
     }
     const std::string& getName() const { return name_;}
     void setName(const std::string& name)  { name_ = name;}
private:
    std::string name_;
    bool value_;
};



class NodeAbc
{
public:
    virtual bool getValue() const = 0;
    virtual std::ostream& operator<<(std::ostream& os) const = 0;
    virtual ~NodeAbc() = 0;
};

NodeAbc::~NodeAbc() { }

std::ostream& operator<<(std::ostream& os, const NodeAbc& rhs)
{
    return rhs << os;
}

class NodeAtom : public NodeAbc
{
public:
    NodeAtom(const Variable* atom)
        : v_(atom)
    {}
    // Default copy OK for Atom.
    virtual bool getValue() const { return v_->getValue();}
    virtual std::ostream& operator<<(std::ostream& os) const
    {
        return os << v_->getName();
    }
private:
    // Not owned, so no free in destructor;
    const Variable* v_;
};

class UnaryOpAbc
{
public:
    // No virtual destructor - stateless type
    virtual bool eval(bool lhs) const = 0;
    virtual  std::string getName() const = 0;

};

class Not : public UnaryOpAbc
{
public:
    virtual bool eval(bool lhs) const { return !lhs;}
    virtual std::string getName() const { return "!";}
};

class BinaryOpAbc
{
public:
        // No virtual destructor - stateless type
    virtual bool eval(bool lhs, bool rhs) const = 0;
    virtual std::string getName() const = 0;
};

class And : public BinaryOpAbc
{
public:
    virtual bool eval(bool lhs, bool rhs) const{ return lhs && rhs;}
    virtual std::string getName() const { return "&&";}
};

class Or : public BinaryOpAbc
{
public:
    virtual bool eval(bool lhs, bool rhs) const{ return lhs || rhs;}
    virtual  std::string getName()const { return "||";}
};


struct Operators
{
    static And and;
    static Or or;
    static Not not;
};

And Operators::and;
Or Operators::or;
Not Operators::not;

class NodeBinary : public NodeAbc
{
public:
    NodeBinary(NodeAbc* lhs, NodeAbc* rhs, const BinaryOpAbc& op )
        : lhs_(lhs),
        rhs_(rhs),
        op_(op)
    {}

    virtual ~NodeBinary()
    {
        delete lhs_;
        delete rhs_;
    }
    virtual bool getValue() const { return op_.eval( lhs_->getValue(), rhs_->getValue());}
    virtual std::ostream& operator<<(std::ostream& os) const
    {
        return os << "(" << *lhs_ << " " << op_.getName() << " " << *rhs_<< " )";
    }

private:
    // No copy;
    NodeBinary(const NodeBinary& other);

    NodeAbc* lhs_;
    NodeAbc* rhs_;
    const BinaryOpAbc& op_;
};

class NodeUnary : public NodeAbc
{
public:
    NodeUnary(NodeAbc* lhs, const UnaryOpAbc& op )
        : lhs_(lhs),
        op_(op)
    {}
    virtual ~NodeUnary()
    {
        delete lhs_;        
    }
    virtual bool getValue() const { return op_.eval( lhs_->getValue());}
    virtual std::ostream& operator<<(std::ostream& os) const
    {
        return os << op_.getName() << *lhs_;
    }
private:
    // No copy.
    NodeUnary(const NodeUnary& other);
    NodeAbc* lhs_;
    const UnaryOpAbc& op_;
};

int main(int argc, _TCHAR* argv[])
{
    std::vector<Variable> variables(4);

    Variable* x1 = &(variables[0] = Variable("x1", true));
    Variable* x2 = &(variables[1] = Variable("x2", true));
    Variable* x3 = &(variables[2] = Variable("x3", true));
    Variable* x4 = &(variables[3] = Variable("x4", true));

    NodeAbc* x1AndX2 = new NodeBinary( new NodeAtom(x1), new NodeAtom(x2), Operators::and);
    NodeAbc* notX4 = new NodeUnary( new NodeAtom(x4),  Operators::not);
    NodeAbc* x3OrNotX4 = new NodeBinary( new NodeAtom(x3),notX4 , Operators::or);
    NodeAbc* root = new NodeBinary(x1AndX2, x3OrNotX4, Operators::or);

    std::cout << * root << "\t" << root->getValue() << std::endl;

    x2->setValue(false);
    x3->setValue(false);

    std::cout << * root << "\t" << root->getValue() << std::endl;

    delete root;

    return 0;
}

答案 1 :(得分:0)

您的树应该存储键值对,这意味着不仅存储x1,还存储它的值(TrueFalse)。以这种方式创建树后,您可以遍历树以查找结果。

答案 2 :(得分:0)

除了你的树,你需要一个符号表 符号表的作用是将变量映射到值:

typedef std::map<std::string, ValueType>    SymbolTable;
SymbolTable    symbolTable;

然后,如果我们假设您的表达式树已经评估了接口。您只需将符号表作为参数传递给评估。

class Node
{
    virtual ValueType  evaluated(SymbolTable const& symbols) = 0;
};
class Variable: public Node
{
    std::string name;
    Variable( std::string const& n) : name(n) {};
    virtual ValueType  evaluated(SymbolTable const& symbols)
    {
        return symbols[name]; // looks up the value of the variable in the symbol table.
    }
};
class NotNode: public Node
{
    std::auto_ptr<Node>    child;
    NotNode(std::auto_ptr<Node> x): child(c) {}
    virtual ValueType  evaluated(SymbolTable const& symbols)
    {
         return child->evaluated(symbols).not();  // Assume Value type knows how to not itself.
    }
}
// etc

当您在根音符上调用evaluate时,您只需传递当前符号表进行评估,然后您应该返回结果。