【问题标题】:Convert a prefix expression tree vector to a ORF/Karva notation expression tree vector将前缀表达式树向量转换为 ORF/Karva 表示法表达式树向量
【发布时间】:2011-06-06 00:16:32
【问题描述】:

好的,这有点棘手。

我有一堆采用表达式树的代码:

((a + b)/(c + d) + sqrt(e))

以前缀形式存储在向量中(我使用的是 C++,但我只需要算法):

+(/(+(a,b),+(c,d)),sqrt(e)) //括号只是为了帮助你阅读。每个运算符和终端都是向量中的一个元素。

现在还有另一种表示表达式树的方法,称为 ORF 形式

(论文第三页:http://arxiv.org/ftp/cs/papers/0102/0102027.pdf

在这种形式中,您可以像从左到右、从上到下阅读树一样表示树。

((a + b)/(c + d) + sqrt(e)) 现在变成:

+/sqrt++eabcd

我一直没有做的是创建一个可以转换的算法:

+/sqrt++eabcd //ORF into:
+(/(+(a,b),+(c,d)),sqrt(e)) //前缀

到目前为止,我只有一些代码来获取不同级别的树的宽度:

bool ConvertPrefixToORF(const std::vector<Node> & individual,
                              std::vector<Node> & ETindividual){
bool all_terminal = false;
int breadth;
int breadthOfDepth[individual.size()];
int depthCounter = 0;
breadthOfDepth[0] = 1;
//Resize only once.
ETindividual.reserve(individual.size());

while (all_terminal == false) {
    //Reset breadth
    breadth = 0;
    //Iterate over next level and calculate depth of level after that.
    for (int i = 0; i < breadthOfDepth[depthCounter]; i++) {
        all_terminal = true;
        //If the individual is a function...
        if (individual[current+i].isFunction()) {
            //Get individual from i'th item at this depth
            function f = individual[current + i];
            //Increment breadth of next level with arity
            breadth += f->getArity();
            //if a single function is found
            all_terminal = false;
        }
    }
    //Go down a level in the tree.
    depthCounter++;
    //Set the breadth of that tree depth:
    breadthOfDepth[depthCounter] = breadth;
}
}

提前感谢您的帮助!这让我很头疼。哦,这对性能至关重要:(

【问题讨论】:

    标签: c++ algorithm expression-trees prefix-tree


    【解决方案1】:

    我的策略是构建解析树,然后深度优先生成前缀符号。

    您可以使用队列从 ORF 构建解析树。当您遇到每个运算符(或术语)时,使其成为队列头部的运算符的子项。当队列头部的节点有足够的孩子时,将其从队列中弹出。

    在您的示例中...从 + 开始并将其推送到队列中(初始元素的特殊情况)。

    下一步处理/。由于队列头部的+ 没有子级(但需要两个),因此您将/ 作为其第一个子级附加到+,并将/ 推入队列。所以现在队列看起来像:

    +/
    

    ...树看起来像

          +
        /   .
      .   .
    

    ...在哪里“。”是一个等待填充的元素。

    接下来是sqrt。由于+ 位于队列的头部并且还没有两个孩子,因此将sqrt 附加到+ 并将sqrt 推送到队列中。所以现在队列看起来像:

    +/sqrt
    

    ...树看起来像

          +
        /   sqrt
      .   .   .
    

    接下来是第二个+。队列的头是第一个+,但现在它已经有了所有的孩子。所以从队列中弹出它。队列的下一个元素是/,它还没有子元素,所以这个+ 成为它的子元素并排在队列的后面。队列现在显示:

    /sqrt+
    

    ...树现在是:

          +
        /    sqrt
      +   .    .
    .   .
    

    接下来第三个+ 成为/ 的第二个孩子并被推入队列。所以队列将是:

    /sqrt++
    

    ...树将是(抱歉,我的 ASCII 艺术很弱):

          +
         /    sqrt
      +    +    .
     . .  . .   
    

    现在/ 已满足,因此当您点击e 时,您会将/ 从队列中弹出。现在sqrt 是队列的开始,所以e 被附加到它上面。队列现在是:

    sqrt++
    

    ...而树是:

          +
         /    sqrt
      +    +    e
     . .  . .
    

    接下来的四次迭代显然将 a、b、c、d 分配给剩余的叶子,从而为您提供解析树。

    顺便说一句,std::dequeue 是用于队列的完美数据结构。

    【讨论】:

      【解决方案2】:

      只需构建一棵树 T。每个节点都是一个元组 (terminal,)(unary_operator, operand)(binary_operator, first_operand, second_operand)。操作数本身就是树中节点的索引。

      例如,表达式a + (b / c) 将具有树T[0] = (+, 1, 2), T[1] = (a,), T[2] = (/, 3, 4), T[3] = (b,), T[4] = (c,)。一旦你有了这个,就做一个预订。这是 Python 代码。

      def preorder(T, i):
        X = [T[i][0]]
        if len(T[i]) > 1:
          X.extend(preorder(T, T[i][1]))
        if len(T[i]) > 2:
          X.extend(preorder(T, T[i][2]))
        return X
      
      def convert(A):
        binary_operators = ['+', '-', '/']
        unary_operators = ['sqrt']
        left = 0
        right = 0
        T = dict([(i, ()) for i in range(len(A))])
        for a in A:
          if a in binary_operators:
            T[left] = (a, right + 1, right + 2)
            right += 2
          elif a in unary_operators:
            T[left] = (a, right + 1)
            right += 1
          else:
            T[left] = (a,)
          left += 1
        return preorder(T, 0)
      
      def main(argv=None):
        A = ['+', '/', 'sqrt', '+', '+', 'e', 'a', 'b', 'c', 'd']
        print convert(A)
      

      当您从 ORF 构建 T 时,保留一个左右指针,它告诉您必须在表达式树中填写的第一个节点,而右指针告诉您最后一个节点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-29
        • 1970-01-01
        • 2011-04-09
        相关资源
        最近更新 更多