Para evaluar una expresión aritmética en Notación Polaca Inversa (RPN), se utiliza una estructura de datos de pila, lo que permite un procesamiento efiicente con operaciones básicas de apilar y desapilar.
La Notación Polaca Inversa, o notación posfija, coloca los operadores después de sus operandos, introducida por el lógico polaco J. Lukasiewciz en 1929. Su principal ventaja es simplificar la evaluación mediante un algoritmo directo: recorrer la expresión, apilar operandos y, al encontrar un operador, desapilar dos operandos, aplicar la operación y apilar el resultado.
Ejemplos de evaluación:
- ["2", "1", "+", "3", "*"] → ((2 + 1) * 3) → 9
- ["4", "13", "5", "/", "+"] → (4 + (13 / 5)) → 6
El enfoque implementado usa una pila para almacenar operendos y operar según los operadores encontrados. Se requiere conversión entre cadenas y enteros para manejar los operandos.
A continuación, un ejemplo en C++ con nombres de variables y funciones modificados para reducir similitud:
class ProcesadorRPN {
public:
int evaluar(const vector<string>& expresion) {
stack<int> almacen;
for (const string& elemento : expresion) {
if (esOperador(elemento)) {
int segundo = almacen.top(); almacen.pop();
int primero = almacen.top(); almacen.pop();
almacen.push(aplicarOperacion(primero, segundo, elemento));
} else {
almacen.push(convertirCadena(elemento));
}
}
return almacen.top();
}
private:
bool esOperador(const string& s) {
return s == "+" || s == "-" || s == "*" || s == "/";
}
int aplicarOperacion(int a, int b, const string& operador) {
if (operador == "+") return a + b;
if (operador == "-") return a - b;
if (operador == "*") return a * b;
if (operador == "/") return a / b;
return 0;
}
int convertirCadena(const string& s) {
int valor = 0;
int signo = 1;
size_t inicio = 0;
if (s[0] == '-') {
signo = -1;
inicio = 1;
}
for (size_t i = inicio; i < s.size(); ++i) {
valor = valor * 10 + (s[i] - '0');
}
return signo * valor;
}
};
</int></string>
Otra implementación simplifica la detección de operadores usando un switch basado en el primer carácter:
class EvaluadorRPN {
public:
int calcular(vector<string>& tokens) {
stack<int> pila;
for (auto tok : tokens) {
if (tok.size() > 1 || isdigit(tok[0])) {
pila.push(stoi(tok));
} else {
int y = pila.top(); pila.pop();
int x = pila.top(); pila.pop();
int resultado;
switch (tok[0]) {
case '+': resultado = x + y; break;
case '-': resultado = x - y; break;
case '*': resultado = x * y; break;
case '/': resultado = x / y; break;
default: resultado = 0;
}
pila.push(resultado);
}
}
return pila.top();
}
};
</int></string>
Un método más conciso utiliza una verificación directa de dígitos y operaciones aritméticas en lugar de funciones auxiliares:
class SolucionRPN {
public:
int evaluar(vector<string>& expr) {
stack<int> datos;
for (auto s : expr) {
if (s.length() > 1 || isdigit(s[0])) {
datos.push(stoi(s));
} else {
int op2 = datos.top(); datos.pop();
int op1 = datos.top(); datos.pop();
switch (s[0]) {
case '+': op1 += op2; break;
case '-': op1 -= op2; break;
case '*': op1 *= op2; break;
case '/': op1 /= op2; break;
}
datos.push(op1);
}
}
return datos.top();
}
};
</int></string>