【问题标题】:How to evaluate expression tree with logical operators in C#如何在 C# 中使用逻辑运算符评估表达式树
【发布时间】:2017-01-24 15:28:07
【问题描述】:

我有一个带有叶节点的树结构,其中包含表达式,这些表达式被断言为 True 或 False ,由逻辑(AND/OR)条件连接。我正在寻找一种算法/解决方案来评估树的深度优先搜索,基于逻辑运算符 如果父节点是 AND,则如果当前节点被评估为 false,则不需要进一步遍历兄弟节点。 (如果当前节点为 TRUE,则如果父节点为 OR,则不再访问兄弟节点) - 这将优化评估。我只是想知道是否已经存在解决方案/代码,而不是重新发明它.

public class TreeNode<T>
{
    private readonly T _value;
    private readonly List<TreeNode<T>> _children = new List<TreeNode<T>>();

    public TreeNode(T value)
    {
        _value = value;
    }

    public TreeNode<T> this[int i]
    {
        get { return _children[i]; }
    }

    public TreeNode<T> Parent { get; private set; }

    public T Value { get { return _value; } }

    public ReadOnlyCollection<TreeNode<T>> Children
    {
        get { return _children.AsReadOnly(); }
    }

    public TreeNode<T> AddChild(T value)
    {
        var node = new TreeNode<T>(value) {Parent = this};
        _children.Add(node);
        return node;
    }

    public TreeNode<T>[] AddChildren(params T[] values)
    {
        return values.Select(AddChild).ToArray();
    }

    public bool RemoveChild(TreeNode<T> node)
    {
        return _children.Remove(node);
    }

    public void Traverse(Action<T> action)
    {
        action(Value);
        foreach (var child in _children)
            child.Traverse(action);
    }

    public IEnumerable<T> Flatten()
    {
        return new[] {Value}.Union(_children.SelectMany(x => x.Flatten()));
    }
}

注意:我可以轻松地在 C# 中进行递归 BFS,但发现这个更难 Image of sample tree structure

【问题讨论】:

  • 问题是什么?你试过什么吗?显示您目前拥有的代码。
  • C# 中的树是如何表示的?到目前为止你尝试过什么?
  • 编辑了问题。我使用显示的代码来创建一棵树。还有一张图片
  • 如果我们在做正确的和/或树pdfs.semanticscholar.org/a7ca/…“And-Or 树的最优深度优先策略”
  • 不是真的,我需要的是给定树的评估算法,可能是 DFS 算法。我可以创建自己的解决方案,但如果可用的话,重用经过验证的现有解决方案会很棒,这样我就可以使用“错误修复时间”来做更好的事情:) 谢谢

标签: c# data-structures tree-traversal


【解决方案1】:

对树进行递归遍历。您收集评估每个子节点的结果,然后应用您的逻辑操作并返回结果。基本逻辑如下。

代码是类似 C# 的伪代码。从您发布的代码中,我不清楚您如何区分运算符节点(AND 和 OR)与具有 True 和 False 值的节点。但是您应该能够使用此基本算法,只需进行一些更改以适应您的代码。

bool EvaluateNode(TreeNode node)
{
    // if it's a child node, return its value
    if (node has no children)
    {
        return node._value;
    }

    switch node.Operator
    {
        case operator.AND:
            // for AND, we can shortcut the evaluation if any child
            // returns false.
            for each child
            {
                if (EvaluateNode(child) == false)
                    return false;
            }
            // all children returned true, so it's true
            return true;

        case operator.OR:
            // for OR, we can shortcut the evaluation if any child
            // returns true.
            for each child
            {
                if (EvaluateNode(child) == true)
                    return true;
            }
            // none were true, so must be false
            return false;
        default:
            // Unknown operator. Some error.
            break;
    }

}

如果您不想进行快捷评估,这仍然有效。你只需稍微改变你的循环。例如,AND 情况是:

bool result = true;
for each child
{
    result = result & EvaluateNode(child);
}
return result;

OR 的情况是:

bool result = false;
for each child
{
    result = result | EvaluateNode(child);
}
return result;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-02
    • 1970-01-01
    相关资源
    最近更新 更多