前缀表达式的评估
前缀和后缀表达式的计算速度比中缀表达式快。这是因为我们不需要处理任何括号或遵循运算符优先规则。在后缀和前缀表达式中,无论其优先级如何,都将首先计算运算符之前的表达式。此外,这些表达式中没有括号。只要我们可以保证使用了有效的前缀或后缀表达式,就可以对其进行正确评估。
我们可以将中缀转换为后缀,也可以将中缀转换为前缀。
在本文中,我们将讨论如何评估用前缀表示法编写的表达式。该方法类似于评估后缀表达式。请阅读后缀表达式的评估以了解如何评估后缀表达式
算法
EVALUATE_PREFIX(STRING)
Step 1: Put a pointer P at the end of the end
Step 2: If character at P is an operand push it to Stack
Step 3: If the character at P is an operator pop two
elements from the Stack. Operate on these elements
according to the operator, and push the result
back to the Stack
Step 4: Decrement P by 1 and go to Step 2 as long as there
are characters left to be scanned in the expression.
Step 5: The Result is stored at the top of the Stack,
return it
Step 6: End
演示算法工作的示例
Expression: +9*26
Character | Stack | Explanation
Scanned | (Front to |
| Back) |
-------------------------------------------
6 6 6 is an operand,
push to Stack
2 6 2 2 is an operand,
push to Stack
* 12 (6*2) * is an operator,
pop 6 and 2, multiply
them and push result
to Stack
9 12 9 9 is an operand, push
to Stack
+ 21 (12+9) + is an operator, pop
12 and 9 add them and
push result to Stack
Result: 21
例子:
Input : -+8/632
Output : 8
Input : -+7*45+20
Output : 25
复杂性该算法具有线性复杂性,因为我们扫描表达式一次并执行最多 O(N) 次推送和弹出操作,这需要恒定的时间。
下面给出算法的实现。
C++
// C++ program to evaluate a prefix expression.
#include
using namespace std;
bool isOperand(char c)
{
// If the character is a digit then it must
// be an operand
return isdigit(c);
}
double evaluatePrefix(string exprsn)
{
stack Stack;
for (int j = exprsn.size() - 1; j >= 0; j--) {
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isOperand(exprsn[j]))
Stack.push(exprsn[j] - '0');
else {
// Operator encountered
// Pop two elements from Stack
double o1 = Stack.top();
Stack.pop();
double o2 = Stack.top();
Stack.pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn[j]) {
case '+':
Stack.push(o1 + o2);
break;
case '-':
Stack.push(o1 - o2);
break;
case '*':
Stack.push(o1 * o2);
break;
case '/':
Stack.push(o1 / o2);
break;
}
}
}
return Stack.top();
}
// Driver code
int main()
{
string exprsn = "+9*26";
cout << evaluatePrefix(exprsn) << endl;
return 0;
}
Java
// Java program to evaluate
// a prefix expression.
import java.io.*;
import java.util.*;
class GFG {
static Boolean isOperand(char c)
{
// If the character is a digit
// then it must be an operand
if (c >= 48 && c <= 57)
return true;
else
return false;
}
static double evaluatePrefix(String exprsn)
{
Stack Stack = new Stack();
for (int j = exprsn.length() - 1; j >= 0; j--) {
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isOperand(exprsn.charAt(j)))
Stack.push((double)(exprsn.charAt(j) - 48));
else {
// Operator encountered
// Pop two elements from Stack
double o1 = Stack.peek();
Stack.pop();
double o2 = Stack.peek();
Stack.pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn.charAt(j)) {
case '+':
Stack.push(o1 + o2);
break;
case '-':
Stack.push(o1 - o2);
break;
case '*':
Stack.push(o1 * o2);
break;
case '/':
Stack.push(o1 / o2);
break;
}
}
}
return Stack.peek();
}
/* Driver program to test above function */
public static void main(String[] args)
{
String exprsn = "+9*26";
System.out.println(evaluatePrefix(exprsn));
}
}
// This code is contributed by Gitanjali
Python3
"""
Python3 program to evaluate a prefix expression.
"""
def is_operand(c):
"""
Return True if the given char c is an operand, e.g. it is a number
"""
return c.isdigit()
def evaluate(expression):
"""
Evaluate a given expression in prefix notation.
Asserts that the given expression is valid.
"""
stack = []
# iterate over the string in reverse order
for c in expression[::-1]:
# push operand to stack
if is_operand(c):
stack.append(int(c))
else:
# pop values from stack can calculate the result
# push the result onto the stack again
o1 = stack.pop()
o2 = stack.pop()
if c == '+':
stack.append(o1 + o2)
elif c == '-':
stack.append(o1 - o2)
elif c == '*':
stack.append(o1 * o2)
elif c == '/':
stack.append(o1 / o2)
return stack.pop()
# Driver code
if __name__ == "__main__":
test_expression = "+9*26"
print(evaluate(test_expression))
# This code is contributed by Leon Morten Richter (GitHub: M0r13n)
C#
// C# program to evaluate
// a prefix expression.
using System;
using System.Collections.Generic;
class GFG {
static Boolean isOperand(char c)
{
// If the character is a digit
// then it must be an operand
if (c >= 48 && c <= 57)
return true;
else
return false;
}
static double evaluatePrefix(String exprsn)
{
Stack Stack = new Stack();
for (int j = exprsn.Length - 1; j >= 0; j--) {
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isOperand(exprsn[j]))
Stack.Push((double)(exprsn[j] - 48));
else {
// Operator encountered
// Pop two elements from Stack
double o1 = Stack.Peek();
Stack.Pop();
double o2 = Stack.Peek();
Stack.Pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn[j]) {
case '+':
Stack.Push(o1 + o2);
break;
case '-':
Stack.Push(o1 - o2);
break;
case '*':
Stack.Push(o1 * o2);
break;
case '/':
Stack.Push(o1 / o2);
break;
}
}
}
return Stack.Peek();
}
/* Driver code */
public static void Main(String[] args)
{
String exprsn = "+9*26";
Console.WriteLine(evaluatePrefix(exprsn));
}
}
/* This code contributed by PrinciRaj1992 */
Javascript
C++
// C++ program to evaluate a prefix expression.
#include
using namespace std;
double evaluatePrefix(string exprsn)
{
stack Stack;
for (int j = exprsn.size() - 1; j >= 0; j--) {
// if jth character is the delimiter ( which is
// space in this case) then skip it
if (exprsn[j] == ' ')
continue;
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isdigit(exprsn[j])) {
// there may be more than
// one digits in a number
double num = 0, i = j;
while (j < exprsn.size() && isdigit(exprsn[j]))
j--;
j++;
// from [j, i] exprsn contains a number
for (int k = j; k <= i; k++)
num = num * 10 + double(exprsn[k] - '0');
Stack.push(num);
}
else {
// Operator encountered
// Pop two elements from Stack
double o1 = Stack.top();
Stack.pop();
double o2 = Stack.top();
Stack.pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn[j]) {
case '+':
Stack.push(o1 + o2);
break;
case '-':
Stack.push(o1 - o2);
break;
case '*':
Stack.push(o1 * o2);
break;
case '/':
Stack.push(o1 / o2);
break;
}
}
}
return Stack.top();
}
// Driver code
int main()
{
string exprsn = "+ 9 * 12 6";
cout << evaluatePrefix(exprsn) << endl;
return 0;
// this code is contributed by Mohd Shaad Khan
}
Java
// Java program to evaluate a prefix expression.
import java.util.*;
public class Main
{
static boolean isdigit(char ch)
{
if(ch >= 48 && ch <= 57)
{
return true;
}
return false;
}
static double evaluatePrefix(String exprsn)
{
Stack stack = new Stack();
for (int j = exprsn.length() - 1; j >= 0; j--) {
// if jth character is the delimiter ( which is
// space in this case) then skip it
if (exprsn.charAt(j) == ' ')
continue;
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isdigit(exprsn.charAt(j))) {
// there may be more than
// one digits in a number
double num = 0, i = j;
while (j < exprsn.length() && isdigit(exprsn.charAt(j)))
j--;
j++;
// from [j, i] exprsn contains a number
for (int k = j; k <= i; k++)
{
num = num * 10 + (double)(exprsn.charAt(k) - '0');
}
stack.push(num);
}
else {
// Operator encountered
// Pop two elements from Stack
double o1 = (double)stack.peek();
stack.pop();
double o2 = (double)stack.peek();
stack.pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn.charAt(j)) {
case '+':
stack.push(o1 + o2);
break;
case '-':
stack.push(o1 - o2);
break;
case '*':
stack.push(o1 * o2);
break;
case '/':
stack.push(o1 / o2);
break;
}
}
}
return stack.peek();
}
// Driver code
public static void main(String[] args) {
String exprsn = "+ 9 * 12 6";
System.out.print((int)evaluatePrefix(exprsn));
}
}
// This code is contributed by mukesh07.
Python3
# Python3 program to evaluate a prefix expression.
def isdigit(ch):
if(ord(ch) >= 48 and ord(ch) <= 57):
return True
return False
def evaluatePrefix(exprsn):
Stack = []
for j in range(len(exprsn) - 1, -1, -1):
# if jth character is the delimiter ( which is
# space in this case) then skip it
if (exprsn[j] == ' '):
continue
# Push operand to Stack
# To convert exprsn[j] to digit subtract
# '0' from exprsn[j].
if (isdigit(exprsn[j])):
# there may be more than
# one digits in a number
num, i = 0, j
while (j < len(exprsn) and isdigit(exprsn[j])):
j-=1
j+=1
# from [j, i] exprsn contains a number
for k in range(j, i + 1, 1):
num = num * 10 + (ord(exprsn[k]) - ord('0'))
Stack.append(num)
else:
# Operator encountered
# Pop two elements from Stack
o1 = Stack[-1]
Stack.pop()
o2 = Stack[-1]
Stack.pop()
# Use switch case to operate on o1
# and o2 and perform o1 O o2.
if exprsn[j] == '+':
Stack.append(o1 + o2 + 12)
elif exprsn[j] == '-':
Stack.append(o1 - o2)
elif exprsn[j] == '*':
Stack.append(o1 * o2 * 5 )
elif exprsn[j] == '/':
Stack.append(o1 / o2)
return Stack[-1]
exprsn = "+ 9 * 12 6"
print(evaluatePrefix(exprsn))
# This code is contributed by divyesh072019.
C#
// C# program to evaluate a prefix expression.
using System;
using System.Collections;
class GFG {
static bool isdigit(char ch)
{
if(ch >= 48 && ch <= 57)
{
return true;
}
return false;
}
static double evaluatePrefix(string exprsn)
{
Stack stack = new Stack();
for (int j = exprsn.Length - 1; j >= 0; j--) {
// if jth character is the delimiter ( which is
// space in this case) then skip it
if (exprsn[j] == ' ')
continue;
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isdigit(exprsn[j])) {
// there may be more than
// one digits in a number
double num = 0, i = j;
while (j < exprsn.Length && isdigit(exprsn[j]))
j--;
j++;
// from [j, i] exprsn contains a number
for (int k = j; k <= i; k++)
{
num = num * 10 + (double)(exprsn[k] - '0');
}
stack.Push(num);
}
else {
// Operator encountered
// Pop two elements from Stack
double o1 = (double)stack.Peek();
stack.Pop();
double o2 = (double)stack.Peek();
stack.Pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn[j]) {
case '+':
stack.Push(o1 + o2);
break;
case '-':
stack.Push(o1 - o2);
break;
case '*':
stack.Push(o1 * o2);
break;
case '/':
stack.Push(o1 / o2);
break;
}
}
}
return (double)stack.Peek();
}
static void Main() {
string exprsn = "+ 9 * 12 6";
Console.Write(evaluatePrefix(exprsn));
}
}
// This code is contributed by divyeshrabadiya07.
Javascript
输出
21
笔记:
要执行更多类型的操作,只需修改 switch case 表。此实现仅适用于单个数字操作数。如果使用一些类似字符的空格来分隔操作数和运算符,则可以实现多位操作数。
下面给出的是允许操作数有多个数字的扩展程序。
C++
// C++ program to evaluate a prefix expression.
#include
using namespace std;
double evaluatePrefix(string exprsn)
{
stack Stack;
for (int j = exprsn.size() - 1; j >= 0; j--) {
// if jth character is the delimiter ( which is
// space in this case) then skip it
if (exprsn[j] == ' ')
continue;
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isdigit(exprsn[j])) {
// there may be more than
// one digits in a number
double num = 0, i = j;
while (j < exprsn.size() && isdigit(exprsn[j]))
j--;
j++;
// from [j, i] exprsn contains a number
for (int k = j; k <= i; k++)
num = num * 10 + double(exprsn[k] - '0');
Stack.push(num);
}
else {
// Operator encountered
// Pop two elements from Stack
double o1 = Stack.top();
Stack.pop();
double o2 = Stack.top();
Stack.pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn[j]) {
case '+':
Stack.push(o1 + o2);
break;
case '-':
Stack.push(o1 - o2);
break;
case '*':
Stack.push(o1 * o2);
break;
case '/':
Stack.push(o1 / o2);
break;
}
}
}
return Stack.top();
}
// Driver code
int main()
{
string exprsn = "+ 9 * 12 6";
cout << evaluatePrefix(exprsn) << endl;
return 0;
// this code is contributed by Mohd Shaad Khan
}
Java
// Java program to evaluate a prefix expression.
import java.util.*;
public class Main
{
static boolean isdigit(char ch)
{
if(ch >= 48 && ch <= 57)
{
return true;
}
return false;
}
static double evaluatePrefix(String exprsn)
{
Stack stack = new Stack();
for (int j = exprsn.length() - 1; j >= 0; j--) {
// if jth character is the delimiter ( which is
// space in this case) then skip it
if (exprsn.charAt(j) == ' ')
continue;
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isdigit(exprsn.charAt(j))) {
// there may be more than
// one digits in a number
double num = 0, i = j;
while (j < exprsn.length() && isdigit(exprsn.charAt(j)))
j--;
j++;
// from [j, i] exprsn contains a number
for (int k = j; k <= i; k++)
{
num = num * 10 + (double)(exprsn.charAt(k) - '0');
}
stack.push(num);
}
else {
// Operator encountered
// Pop two elements from Stack
double o1 = (double)stack.peek();
stack.pop();
double o2 = (double)stack.peek();
stack.pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn.charAt(j)) {
case '+':
stack.push(o1 + o2);
break;
case '-':
stack.push(o1 - o2);
break;
case '*':
stack.push(o1 * o2);
break;
case '/':
stack.push(o1 / o2);
break;
}
}
}
return stack.peek();
}
// Driver code
public static void main(String[] args) {
String exprsn = "+ 9 * 12 6";
System.out.print((int)evaluatePrefix(exprsn));
}
}
// This code is contributed by mukesh07.
Python3
# Python3 program to evaluate a prefix expression.
def isdigit(ch):
if(ord(ch) >= 48 and ord(ch) <= 57):
return True
return False
def evaluatePrefix(exprsn):
Stack = []
for j in range(len(exprsn) - 1, -1, -1):
# if jth character is the delimiter ( which is
# space in this case) then skip it
if (exprsn[j] == ' '):
continue
# Push operand to Stack
# To convert exprsn[j] to digit subtract
# '0' from exprsn[j].
if (isdigit(exprsn[j])):
# there may be more than
# one digits in a number
num, i = 0, j
while (j < len(exprsn) and isdigit(exprsn[j])):
j-=1
j+=1
# from [j, i] exprsn contains a number
for k in range(j, i + 1, 1):
num = num * 10 + (ord(exprsn[k]) - ord('0'))
Stack.append(num)
else:
# Operator encountered
# Pop two elements from Stack
o1 = Stack[-1]
Stack.pop()
o2 = Stack[-1]
Stack.pop()
# Use switch case to operate on o1
# and o2 and perform o1 O o2.
if exprsn[j] == '+':
Stack.append(o1 + o2 + 12)
elif exprsn[j] == '-':
Stack.append(o1 - o2)
elif exprsn[j] == '*':
Stack.append(o1 * o2 * 5 )
elif exprsn[j] == '/':
Stack.append(o1 / o2)
return Stack[-1]
exprsn = "+ 9 * 12 6"
print(evaluatePrefix(exprsn))
# This code is contributed by divyesh072019.
C#
// C# program to evaluate a prefix expression.
using System;
using System.Collections;
class GFG {
static bool isdigit(char ch)
{
if(ch >= 48 && ch <= 57)
{
return true;
}
return false;
}
static double evaluatePrefix(string exprsn)
{
Stack stack = new Stack();
for (int j = exprsn.Length - 1; j >= 0; j--) {
// if jth character is the delimiter ( which is
// space in this case) then skip it
if (exprsn[j] == ' ')
continue;
// Push operand to Stack
// To convert exprsn[j] to digit subtract
// '0' from exprsn[j].
if (isdigit(exprsn[j])) {
// there may be more than
// one digits in a number
double num = 0, i = j;
while (j < exprsn.Length && isdigit(exprsn[j]))
j--;
j++;
// from [j, i] exprsn contains a number
for (int k = j; k <= i; k++)
{
num = num * 10 + (double)(exprsn[k] - '0');
}
stack.Push(num);
}
else {
// Operator encountered
// Pop two elements from Stack
double o1 = (double)stack.Peek();
stack.Pop();
double o2 = (double)stack.Peek();
stack.Pop();
// Use switch case to operate on o1
// and o2 and perform o1 O o2.
switch (exprsn[j]) {
case '+':
stack.Push(o1 + o2);
break;
case '-':
stack.Push(o1 - o2);
break;
case '*':
stack.Push(o1 * o2);
break;
case '/':
stack.Push(o1 / o2);
break;
}
}
}
return (double)stack.Peek();
}
static void Main() {
string exprsn = "+ 9 * 12 6";
Console.Write(evaluatePrefix(exprsn));
}
}
// This code is contributed by divyeshrabadiya07.
Javascript
输出
81
时间复杂度: O(n)
空间复杂度: O(n)