Двоичное выражение дерева Переполнение стека

У меня небольшая проблема. Я пытаюсь добавить математическое выражение в двоичное дерево, но не могу понять алгоритм. Вот:

If the current token is a '(':
Add a new node as the left child of the current node, and
descend to the left child.
If the current token is in the list ['+','-','/','*']:
Set the root value of the current node to the operator represented by the current token.
Add a new node as the right child of the current node and descend to the right child.
If the current token is a number:
Set the root value of the current node to the number and return to the parent.
If the current token is a ')':
go to the parent of the current node.

и код, который я сделал до сих пор:

template<class T>
void Tree<T>::Expr(Node<T> *node, char expr[], int &i)
{
i++;
T x = expr[i];
if(x == '(')
{
node = node->Left;

node = new Node<T>;
node->Left = NULL;
node->Right = NULL;
Expr(node, expr, i);
}
if(x == '+' || x == '-' || x == '*' || x == '/')
{
node->data = x;
node = node->Right;
node = new Node<T>;
node->Left = NULL;
node->Right = NULL;
Expr(node, expr, i);
}
if(x >= '0' && x <= '9')
{
node->data = x;
return;
}
if(x == ')') return;
}

Я знаю, что это большой беспорядок, но я не могу понять, как это реализовать. Может кто-нибудь объяснить мне алгоритм или дать мне исходный код на C ++ или лучше объяснил алгоритм?

Постскриптум Вот новый код, который я написал, но он работает только для таких выражений, как: (5 + 2)

template<class T>
void Tree<T>::Expr(Node<T> *&node, char expr[], int &i)
{
i++;
if(i >= strlen(expr)) return;
char x = expr[i];
node = new Node<T>;
node->Left = NULL;
node->Right = NULL;
if(x == '(')
{
Expr(node->Left, expr, i);
i++;
x = expr[i];
}
if(x >= '0' && x <= '9')
{
node->data = x;
return;
}
if(x == '+' || x == '-' || x == '*' || x == '/')
{
node->data = x;
Expr(node->Right, expr, i);
}
if(x == ')') return;
}

2

Решение

Вот пример, который я сделал для целей обучения давным-давно:

#include <iostream>
#include <list>
#include <cassert>
#include <stdexcept>

/// \todo Because I'm short of time, there is no smart pointers or
/// even destructors (w/ delete) :) -- THIS IS FAR FROM PRODUCTION CODE,
/// but it is minimalistic to realize the idea...

/**
* \brief Expression abstract base class
*
* ... has only evaluate function.
*/
struct expression
{
virtual ~expression() {};
virtual int operator()() const = 0;
};

struct number_token : public expression
{
int value_;
number_token(const int value = 0) : value_(value) {}
int operator()() const {
return value_;
}
};

struct binary_predicate : public expression
{
expression* left_;
expression* right_;

binary_predicate(expression* const left = 0, expression* const right = 0)
: left_(left), right_(right)
{}
};

struct plus : public binary_predicate
{
plus(expression* const left, expression* const right)
: binary_predicate(left, right)
{}

int operator()() const {
return (*left_)() + (*right_)();
}
};

struct minus : public binary_predicate
{
minus(expression* const left, expression* const right)
: binary_predicate(left, right)
{}

int operator()() const {
return (*left_)() - (*right_)();
}
};

struct mul : public binary_predicate
{
mul(expression* const left, expression* const right)
: binary_predicate(left, right)
{}

int operator()() const {
return (*left_)() * (*right_)();
}
};

struct div : public binary_predicate
{
div(expression* const left, expression* const right)
: binary_predicate(left, right)
{}

int operator()() const {
return (*left_)() / (*right_)();
}
};

class evaluator
{
public:
const expression* parse(const char*);                   ///< Parse an expression

private:
expression* parse_number(const char*&);                 ///< Parse numeric constants
expression* parse_atom(const char*&);                   ///< Parse nested expression
expression* parse_summands(const char*&);               ///< Parse '+' and '-' operations
expression* parse_factors(const char*&);                ///< Parse '*' and '/' operations
};

expression* evaluator::parse_number(const char*& s)
{
assert("Sanity check" && s && std::isdigit(*s));
number_token* nt = new number_token(0);
// Convert number...
while (*s && std::isdigit(*s))
{
nt->value_ = nt->value_ * 10 + *s++ - '0';
}
return nt;
}

expression* evaluator::parse_atom(const char*& s)
{
assert("Sanity check" && s);
if (*s == 0)
{
throw std::runtime_error("Atom parse error: unexpected EOS");
}
else if (*s == '(')
{
s++;
expression* atom = parse_summands(s);
if (*s == ')')
{
s++;
return atom;
}
throw std::runtime_error("Atom parse error: unbalanced brackets");

}
else if (std::isdigit(*s))
{
expression* atom = parse_number(s);
return atom;
}
throw std::runtime_error("Atom parse error: unexpected char");
}

expression* evaluator::parse_factors(const char*& s)
{
assert("Sanity check" && s);
expression* left = parse_atom(s);
while (*s)
{
if (*s == '*')
{
s++;
expression* right = parse_atom(s);
left = new mul(left, right);
continue;
}
else if (*s == '/')
{
s++;
expression* right = parse_atom(s);
left = new div(left, right);
continue;
}
return left;
}
return left;
}

expression* evaluator::parse_summands(const char*& s)
{
assert("Sanity check" && s);
expression* left = parse_factors(s);
while (*s)
{
if (*s == '+')
{
s++;
expression* right = parse_factors(s);
left = new plus(left, right);
continue;
}
else if (*s == '-')
{
s++;
expression* right = parse_factors(s);
left = new minus(left, right);
continue;
}
return left;
}
return left;
}

const expression* evaluator::parse(const char* s)
{
return parse_summands(s);
}int evaluate(const char* const e)
{
evaluator ev;
const expression* const ex = ev.parse(e);
assert("Sanity check" && ex);
return (*ex)();
}

// s= evaluate(“(4+3)*2/5” );
// s= evaluate(“((12+9)/2)*5”);
int main()
{
{
int a = evaluate("(4+3)*2/5");
assert("Unexpected result" && a == 2);
std::cout << "\"(4+3)*2/5\" = " << a << std::endl;
}
{
int a = evaluate("((12+9)/2)*5");
assert("Unexpected result" && a == 50);
std::cout << "\"((12+9)/2)*5\" = " << a << std::endl;
}
return 0;
}
3

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector