Я написал код для преобразования дерева выражений в предварительный и последующий порядок, но я изо всех сил пытаюсь построить дерево выражения из инфиксного выражения. У меня есть файл .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: error: 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();

Я знаю, почему возникают две последние ошибки (не объявленные в области видимости), но я просто не знаю, что делать, чтобы исправить это, пока мой код работает правильно.

Я даже не знаю, ошибочен ли мой код, но любые советы были бы очень признательны! Благодарю.

EDIT: это классы, которые влияют на функцию 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*);
};
0
user6276841 11 Май 2016 в 08:28

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' или чем-то еще, что означает пустое значение.

Работа ) должна заключаться в том, чтобы вытащить вершину из стека и положить ее туда, куда нужно. Это будет либо следующий верхний левый узел, если его значение null, в противном случае это будет верхний правый узел. Вам не нужно повторять цикл вниз по стеку, как вы это делаете, потому что это всегда будет только вершина, в которой мы заинтересованы.

Задача числа должна заключаться в том, чтобы создать себя как новый узел и поместить себя туда, куда ему нужно. Точно так же, как ), который будет либо верхним левым узлом, если его значение равно нулю, в противном случае это будет верхний правый узел. В своем коде вы создаете узел, но не помещаете его нигде, кроме как в стек. Это не приносит никакой пользы, потому что числовой узел всегда будет листовым узлом (ни правым, ни левым).

Наконец, задача операции должна заключаться в том, чтобы просто установить себя на вершину 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();
}
0
kmdreko 11 Май 2016 в 07:11

Беглый взгляд показывает, что вам нужен ETNode *temp = new ETNode; сразу после while(tree_stack.top() != '('). Но логику я не проверял.

0
Adrian Roman 11 Май 2016 в 05:50