Оценить выражение двоичного дерева 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