【问题标题】:Read infix expression into a stack将中缀表达式读入堆栈
【发布时间】:2016-09-06 07:56:03
【问题描述】:

我已经编写了将表达式树转换为前序和后序的代码,但我正在努力从中缀表达式实际构建表达式树。我有一个 .cc 文件,它将调用 build_expression_tree 函数,调用转换函数并打印出转换后的表达式。

这是我当前的非工作功能:

void Expression_Tree::build_expression_tree(char input[], int size)
{
    for (int i = 0; i < size; i++) 
    {
        if (input[i] == ' ')
        {
            i++;
        }
        if(input[i] >= '0' && input[i] <= 9) 
        { 
            ETNode *temp = new ETNode;
            temp->left = temp->right = NULL;
            temp->input = input[i];

            tree_stack.push(temp);
        }
        else if (input[i] == '(') 
        {
            ETNode *temp = new ETNode;
            temp->left = temp->right = NULL;
            temp->input = input[i];

            tree_stack.push(temp);
        }
        else if (input[i] == ')')
        {
            while (tree_stack.top() != '(')
            {
                temp->right = tree_stack.top();
                tree_stack.pop();
                temp->left = tree_stack.top();
                tree_stack.pop();
                tree_stack.pop();
                tree_stack.push(temp);
            }
        }
        else if (input[i] == '+' || input[i] == '-' || input[i] == '*' || input[i] == '/')
        {
            while (!tree_stack.empty())
            {
                ETNode *temp = new ETNode;
                temp->left = temp->right = NULL;
                temp->input = input[i];

                tree_stack.push(temp);

                temp->right = tree_stack.top();
                tree_stack.pop();
                temp->left = tree_stack.top();
                tree_stack.pop();

                tree_stack.push(temp);
            }
        }
    }
}

此时我遇到的错误是: Expression_Tree.h:61:40: 错误:ISO C++ 禁止指针和整数之间的比较

while(tree_stack.top() != '(')

Expression_Tree.h:62:13: 错误:'temp' 未在此范围内声明

temp->right = tree_stack.top();

Expression_Tree.h:62:13: 错误:'temp' 未在此范围内声明

temp->left = tree_stack.top();

我知道为什么会发生最后两个错误(未在范围内声明),但我只是不知道在使我的代码正常工作的同时如何修复它。

我什至不知道我的代码是否完全错误,但任何提示都将不胜感激! 谢谢。

编辑: 这些是影响 Build_Expression_Tree 函数的类。

class ETNode {
public:
    char input;
    ETNode *left, *right;
};

class Expression_Tree { 
public:
    Expression_Tree() { root = 0; };
    ~Expression_Tree() { clear(root); }
    void build_expression_tree(char[], int);
    void inorder() { inorder(root); }
    void preorder() { preorder(root); }
    void postorder() {postorder(root); }
private:
    ETNode* root;
    std::stack<ETNode*> tree_stack;
    void visit(ETNode* p) { std::cout << p->input << " "; } 
    void inorder(ETNode*);
    void preorder(ETNode*);
    void postorder(ETNode*);
    void clear(ETNode*);
};

【问题讨论】:

  • 请告诉我们tree_stackETNode是什么
  • @vu1p3n0x 我已经编辑了帖子
  • 您能否澄清一下,您只是将堆栈用作构建辅助工具吗?并且只使用root 进行所有其他操作?还是您需要以某种方式保留堆栈?
  • ()s 在您的输入中也是强制性的吗?或者有人可以写(5 + 2 + 3)吗?
  • @vu1p3n0x 堆栈纯粹用于构建树,构建函数由测试函数调用以在打印前发送到预排序/后排序函数。这些是我试图实现的步骤: 1. 将输入读入新的树节点,将它们添加到堆栈中,直到找到右括号。 2. 通过从堆栈中弹出三个项目来回溯。 3. 从这三个项目构建一个子树。 4. 从堆栈中删除匹配的左括号。 5. 将子树添加到堆栈中(实际上只是子树的根节点)。 6. 重复 1-5,直到删除所有括号。

标签: c++ stack expression-trees infix-notation


【解决方案1】:

快速浏览会发现您需要在while(tree_stack.top() != '(') 之后使用ETNode *temp = new ETNode;。不过,我没有检查逻辑。

【讨论】:

  • 是的,谢谢,问题更多的是 while 循环错误。
【解决方案2】:

在这里,我将您的示例输入拆分为如何使用堆栈以及在每个输入处做出的决策的表示。

//    _ = nullptr or empty
//    # = pointer to subtree (not just a number)
// | ___ |     |     |     begin (empty element on stack)
// | 2__ |     |     |  2  make number node and set to top->left if empty, else top->right
// | 2+_ |     |     |  +  set top->input if not set, else pop parent into left of new node
// | 2+_ | ___ |     |  (  make new node on stack
// | 2+_ | 3__ |     |  3  make number node and set to top->left if empty, else top->right
// | 2+_ | 3*_ |     |  *  set top->input if not set, else pop parent into left of new node
// | 2+_ | 3*_ | ___ |  (  make new node on stack
// | 2+_ | 3*_ | 2__ |  2  make number node and set to top->left if empty, else top->right
// | 2+_ | 3*_ | 2+_ |  +  set top->input if not set, else pop parent into left of new node
// | 2+_ | 3*_ | 2+2 |  2  make number node and set to top->left if empty, else top->right
// | 2+_ | 3*# |     |  )  pop it off into its parent
// | 2+# |     |     |  )  pop it off into its parent
// | #+_ |     |     |  +  set top->input if not set, else pop parent into left of new node
// | #+5 |     |     |  5  make number node and set to top->left if empty, else top->right

请注意,我有许多重复语句,一种用于(,一种用于),一种用于数字0-9,一种用于每个操作+-*/。您的代码中已经有了这些划分,因此您走在了正确的轨道上。

( 的唯一工作应该是在堆栈顶部创建一个新节点。在您的代码中,没有必要设置input = '(',因为它稍后会被实际输入覆盖,并且它在堆栈中的位置就是跟踪它所需要的。您应该将 input 初始化为 '\0' 或其他意味着空的东西。

) 的工作应该是将栈顶从栈顶弹出并放到需要去的地方。如果它为空,那将是下一个顶部的左节点,否则它将是顶部的右节点。你不需要像你那样循环堆栈,因为它总是只是我们有兴趣弹出的顶部。

一个数字的工作应该是将自己创建为一个新节点并将自己放在需要去的地方。就像) 一样,如果它为空,它要么是顶部的左节点,否则它将是顶部的右节点。在您的代码中,您创建了节点,但除了堆栈之外,您没有将其放在任何地方。它在那里没有任何好处,因为数字节点将始终是叶节点(没有右或左)。

最后,操作的工作应该是简单地将自己设置为顶部的input。但是,有一种特殊情况,顶部已经被填充(当您执行 1+2+3 时,1+2 是顶部的节点)。所以在这种情况下你可以做的是从顶部弹出,在顶部推送一个新节点,将旧顶部添加为左侧,然后将自身设置为顶部的input。你不需要循环。

全部完成后,您可以设置root = tree_stack.top()

如果你想要我可以提供的代码,但我希望我的解释就足够了。

代码:这似乎对我有用

void Expression_Tree::build_expression_tree(char input[], int size)
{
  // assuming empty tree_stack, it shouldn't really be a member 
  // variable since its only used for building
  //std::stack<ETNode*> tree_stack;

  // make empty node, should really make a default constructor set all this up
  tree_stack.push(new ETNode);
  tree_stack.top()->left  = nullptr;
  tree_stack.top()->right = nullptr;
  tree_stack.top()->input = '\0';

  for (int i = 0; i < size; i++)
  {
    if (input[i] == ' ')
    {
      i++;
    }
    if (input[i] >= '0' && input[i] <= '9') // this 9 had a typo before
    {
      // create number leaf
      ETNode *temp = new ETNode;
      temp->left = nullptr;
      temp->right = nullptr; 
      temp->input = input[i];

      // put where it needs to go
      if (tree_stack.top()->left == nullptr)
        tree_stack.top()->left = temp;
      else
        tree_stack.top()->right = temp;
    }
    else if (input[i] == '(')
    {
      // make empty node
      ETNode *temp = new ETNode;
      temp->left = nullptr;
      temp->right = nullptr;
      temp->input = '\0';

      tree_stack.push(temp);
    }
    else if (input[i] == ')')
    {
      // pop top from the stack
      ETNode *temp = tree_stack.top();
      tree_stack.pop();

      // put where it needs to go
      if (tree_stack.top()->left == nullptr)
        tree_stack.top()->left = temp;
      else
        tree_stack.top()->right = temp;
    }
    else if (input[i] == '+' || input[i] == '-' || input[i] == '*' || input[i] == '/')
    {
      // shuffle node if already filled
      if (tree_stack.top()->input != '\0')
      {
        ETNode *old = tree_stack.top();
        tree_stack.pop();

        ETNode *temp = new ETNode;
        temp->left = old;
        temp->right = nullptr;

        tree_stack.push(temp);
      }

      tree_stack.top()->input = input[i];
    }
  }

  // set root node
  root = tree_stack.top();
}

【讨论】:

  • 非常感谢,我已经尝试转换我的代码以按照您的步骤进行操作,并且我认为我已经相当接近了,但我仍在努力让它整体工作。如果您不介意,我希望您的代码能够交叉引用并理解我哪里出错了。如果没有,别担心,我会努力把它磨出来。谢谢大家
  • 已编辑以提供一些代码。希望它可以帮助您更好地理解它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 1970-01-01
  • 2016-06-18
  • 2012-09-22
  • 1970-01-01
  • 1970-01-01
  • 2020-07-15
相关资源
最近更新 更多