Оценить выражение двоичного дерева C++

Я пытался изучить эту реализацию двоичного дерева, которое оценивает выражение. Я не смог запустить его и посмотреть вывод. Как бы я получил 3*(7+1)/4+(17-5), что приводит к 18. Вот ссылка http://math.hws.edu/eck/cs225/s03/binary_trees/

class ExpNode {
          // Represents a node of any type in an expression tree.
          // This is an "abstract" class, since it contains an undefined
          // function, value(), that must be defined in subclasses.
          // The word "virtual" says that the defintion can change
          // in a subclass.  The "= 0" says that this function has
          // no definition in this class.

     public:     

       virtual double value() = 0;  // Return the value of this node.

   }; // end class ExpNode


class ConstNode : public ExpNode {
          // Represents a node that holds a number.  (The
          // ": public ExpNode" says that this class is
          // a subclass of ExpNode.)

       double number;  // The number in the node.

     public:

       ConstNode( double val ) {
             // Constructor.  Create a node to hold val.
          number = val;
       }

       double value() {
             // The value is just the number that the node holds.
          return number;
       }

    }; // end class ConstNode


class BinOpNode : public ExpNode {
          // Represents a node that holds an operator.

       char op;        // The operator.
       ExpNode *left;   // The left operand.
       ExpNode *right;  // The right operand.

     public:

       BinOpNode( char op, ExpNode *left, ExpNode *right ) {
             // Constructor.  Create a node to hold the given data.
          this->op = op;
          this->left = left;
          this->right = right;
       }

       double value() {
             // To get the value, compute the value of the left and
             // right operands, and combine them with the operator.
           double leftVal = left->value();
           double rightVal = right->value();
           switch ( op ) {
               case '+':  return leftVal + rightVal;
               case '-':  return leftVal - rightVal;
               case '*':  return leftVal * rightVal;
               case '/':  return leftVal / rightVal;
            }
       }

    }; // end class BinOpNode

Вот моя попытка сделать основную функцию:

int main() {
    BinOpNode *opnode;
    opnode = new BinOpNode;
    opnode->value()=5;
    ExpNode *expnode;
    expnode = opnode;
    expnode->value();
    return 0;

}

Не компилируется, это ошибки

15:58:27 **** Incremental Build of configuration Debug for project ExpNode ****
Info: Internal Builder is used for build
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o "src\\ExpNode.o" "..\\src\\ExpNode.cpp" 
..\src\ExpNode.cpp: In function 'int main()':
..\src\ExpNode.cpp:60:15: error: no matching function for call to 'BinOpNode::BinOpNode()'
..\src\ExpNode.cpp:36:2: note: candidates are: BinOpNode::BinOpNode(char, ExpNode*, ExpNode*)
..\src\ExpNode.cpp:30:33: note:                 BinOpNode::BinOpNode(const BinOpNode&)
..\src\ExpNode.cpp:61:18: error: lvalue required as left operand of assignment

15:58:28 Build Finished (took 405ms)

3 ответа

Решение

В C++ конструкторы по умолчанию работают интересно.

Если вы не определяете никаких конструкторов, для вас создается конструктор по умолчанию:

class A {};

int main()
{
    A a; // perfectly fine

Но если вы определите любой другой конструктор, эти сгенерированные конструкторы исчезнут:

class A
{
    A(int) { ... }
};

int main()
{
    A a; // ERROR!
}

В этом сценарии конструктор по умолчанию не существует, потому что вы его определили, а компилятор не сгенерировал его для вас.

Это ваша проблема, потому что здесь, в main, у вас есть эта строка:

opnode = new BinOpNode;

который запускает конструктор по умолчанию BinOpNode, Посмотри на свой BinOpNode конструкторы:

BinOpNode( char op, ExpNode *left, ExpNode *right )

Эй, смотрите: это не конструктор по умолчанию!

У вас есть два варианта: либо добавить конструктор по умолчанию в класс:

BinOpNode() { ... }

или используйте аргументы при вызове new:

opnode = new BinOpNode(op, left, right);

Удачи!

Я думаю, что проблема в логике вашей функции main().

Согласно определению данных классов, сначала вы должны создать объект типа ConstNode для каждого числа в выражении. Затем вы должны создать BinOpNode для каждого оператора в выражении.

И, кстати, это выражение оценивает до 18, а не 82!

Что-то вроде этого:

//3*(7+1)/4+(17-5)  = 18
int main()
{
  BinOpNode *a, *b;
  a = new BinOpNode('+', new ConstNode(7), new ConstNode(1));
  a = new BinOpNode('*', new ConstNode(3), a);
  a = new BinOpNode('/', a, new ConstNode(4));
  b = new BinOpNode('-', new ConstNode(17), new ConstNode(5));
  b = new BinOpNode('+', a, b);
  cout << b->value();
}

PS: мы можем передать объект класса ConstNode когда объект ExpNode ожидается в конструкторе BinOpNode как ConstNode наследуется от ExpNode абстрактный базовый класс.

Ни один из классов не имеет конструкторов по умолчанию.
value возвращает результат вычисления выражения, и вам необходимо передать необходимые части выражения в качестве его параметров при его создании.
(Неясно, как вы ожидаете, что сможете присвоить значение 5 двоичному выражению.)

Вам нужно построить дерево из листьев (которые будут постоянными) по направлению к корню.
В качестве примера вот выражение 5 + 3:

ConstNode five(5);
ConstNode three(3);
BinOpNode fiveplusthree('+', &five, &three);
std::cout << fiveplusthree.value(); // Should print 8
Другие вопросы по тегам