【问题标题】:About Trees and Prefix (Polish) Notation?关于树和前缀(波兰语)表示法?
【发布时间】:2009-02-07 15:31:35
【问题描述】:

我的 MIPS 汇编课程要求我将未知大小的表达式读入解析树。我从来不用处理树,所以这就是我存储值的方式:

假设用户输入了表达式 1 + 3 - 4(每个操作数只能是数字 1-9)

我最左边的子节点将是起点并包含 2 条数据

1. The operand
2. Pointer to the next node (operator)

这就是我构建树的方式。我会从操作数指向运算符,再指向下一个操作数,再指向下一个运算符,直到没有更多值要读入为止。

我的下一个任务是递归遍历树并以中缀/前缀/后缀表示法输出值。

考虑到我是如何构建树的,中缀遍历没有问题。

我卡在前缀上。首先,我没有完全理解。

当我在前缀中输出我们的表达式 (1 + 3 - 4) 时,它应该出现 - + 1 3 4 吗?我无法按照在线示例进行操作。

您还认为我的树构造正确吗?我的意思是,我无法从当前节点转到前一个节点,这意味着我总是必须从最左边的子节点开始遍历,尽管我的 TA 说这是要走的路,但本能地听起来并不正确。

感谢您的帮助。

【问题讨论】:

    标签: tree mips traversal prefix notation


    【解决方案1】:

    您的解析树应该如下所示:

    '-' | +---+---+ | | '+' '4' | +---+---+ | | '1' '3'

    每个节点都有两个指针。一个给它的左孩子,一个给它的右孩子。使用递归遍历时,不需要指向父节点的指针。

    这是一些伪代码:

    中缀符号的遍历:

    void traverse(Node *node) {
        if (node->leftChild != 0) {
            traverse(node->leftChild);
        }
    
        print(node->value);
    
        if (node->rightChild != 0) {
            traverse(node->rightChild);
        }
    }
    

    前缀符号的遍历:

    void traverse(Node *node) {
        print(node->value);
    
        if (node->leftChild != 0) {
            traverse(node->leftChild);
        }
    
        if (node->rightChild != 0) {
            traverse(node->rightChild);
        }
    }
    

    后缀符号的遍历:

    void traverse(Node *node) {
        if (node->leftChild != 0) {
            traverse(node->leftChild);
        }
    
        if (node->rightChild != 0) {
            traverse(node->rightChild);
        }
    
        print(node->value);
    }
    

    您可以使用树的根节点调用 traverse 方法。

    您的Node 数据结构需要三个成员:

    struct Node {
        char value;
        Node *leftChild;
        Node *rightChild;
    }
    

    树的叶子将包含leftChildrightChild 的空指针。

    有时用更高级的语言(无论你觉得什么都舒服)编写这些东西有助于理解问题,然后将这些代码“翻译”成汇编程序。我记得像这样在 MIPS 汇编器中编写 blocks world 模拟。

    【讨论】:

      【解决方案2】:

      一般而言,您应该以这样一种方式构造一棵树,即所有叶节点(没有子节点的节点)都是操作数,而内部节点(其他所有节点)都是运算符。这应该使得操作符节点的子节点是它的操作数,或者本身就是具有操作数的操作符。如果你能以这种方式构造一棵树,那么形成各种符号(前缀、后缀、中缀)就相当简单——你只需遵循树的前序、后序和中序遍历,这有众所周知的算法。

      据我所知,您构建的不是树,而是链表,这对您没有好处。你有 2 个不同的实体——操作数和运算符——你必须区别对待它们。

      【讨论】:

      • 这与我即将给出的答案相同。谢谢 sykora!
      【解决方案3】:

      我同意 sykora 的说法。我想补充一点,在这种情况下您也可以使用堆栈。如果您的任务要求您专门使用一棵树,那么 sykora 的建议效果最好。但是,堆栈可能更容易为简单的表达式求值编程。

      【讨论】:

        【解决方案4】:

        这是编译的一般问题的一个实例,这是一个已解决的问题。如果您对编译技术进行 google,您将找到与您的问题相关的各种信息。

        您的图书馆应该有一本编译器:原理、技术和工具,作者是 Aho、Sethi 和 Ullman。如果没有,请要求购买(这是该领域的标准工作)。 它的第一部分应该对您有所帮助。

        Third edition link

        【讨论】:

          猜你喜欢
          • 2016-07-23
          • 2016-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多