栈用法:后缀表达式的求值

2021年3月9日16:14:24 发表评论 1,078 次浏览

本文概述

后缀表示法用于表示代数表达式。与后缀形式相比, 以后缀形式编写的表达式的求值速度更快后缀不需要括号中的括号表示法。我们已经讨论过后缀到后缀的转换。在这篇文章中, 讨论了后缀表达式的评估。

以下是评估后缀表达式的算法

1)创建一个堆来存储操作数(或值)。

2)扫描给定的表达式, 然后对每个扫描的元素执行以下操作。

…..a)如果元素是数字, 则将其推入堆

…..b)如果元素是运算符, 请从堆栈中弹出该运算符的操作数。评估运算符并将结果推回堆栈

3)表达式结束时, 堆栈中的数字是最终答案

例子:

令给定的表达式为" 2 3 1 * + 9-"。我们一一扫描所有元素。

1)扫描" 2", 它是一个数字, 因此将其压入堆栈。堆叠中包含" 2"

2)扫描" 3", 再次扫描一个数字, 将其推入堆栈, 堆栈现在包含" 2 3"(从下到上)

3)扫描" 1", 再扫描一个数字, 将其推入堆栈, 堆栈现在包含" 2 3 1"

4)扫描" *", 它是一个运算符, 从堆栈中弹出两个操作数, 将*运算符应用于操作数, 我们得到3 * 1, 结果为3。将结果" 3"压入堆栈。堆叠现在变为" 2 3"。

5)扫描" +", 它是一个运算符, 从堆栈中弹出两个操作数, 将+运算符应用于操作数, 我们得到3 + 2, 结果为5。将结果" 5"压入堆栈。堆叠现在变为" 5"。

6)扫描" 9", 它是一个数字, 我们将其压入堆栈。堆叠现在变为" 5 9"。

7)扫描"-", 它是一个运算符, 从堆栈中弹出两个操作数, 将–运算符应用于操作数, 我们得到5 – 9, 结果为-4。我们将结果" -4"推入堆栈。堆叠现在变为" -4"。

8)没有更多要扫描的元素, 我们从堆栈中返回顶部元素(这是堆栈中剩下的唯一元素)。

推荐:请在"实践首先, 在继续解决方案之前。

下面是上述算法的实现。

C ++

// C++ program to evaluate value of a postfix expression 
#include <iostream> 
#include <string.h> 
  
using namespace std;
  
// Stack type 
struct Stack 
{ 
     int top; 
     unsigned capacity; 
     int * array; 
}; 
  
// Stack Operations 
struct Stack* createStack( unsigned capacity ) 
{ 
     struct Stack* stack = ( struct Stack*) malloc ( sizeof ( struct Stack)); 
  
     if (!stack) return NULL; 
  
     stack->top = -1; 
     stack->capacity = capacity; 
     stack->array = ( int *) malloc (stack->capacity * sizeof ( int )); 
  
     if (!stack->array) return NULL; 
  
     return stack; 
} 
  
int isEmpty( struct Stack* stack) 
{ 
     return stack->top == -1 ; 
} 
  
char peek( struct Stack* stack) 
{ 
     return stack->array[stack->top]; 
} 
  
char pop( struct Stack* stack) 
{ 
     if (!isEmpty(stack)) 
         return stack->array[stack->top--] ; 
     return '$' ; 
} 
  
void push( struct Stack* stack, char op) 
{ 
     stack->array[++stack->top] = op; 
} 
  
  
// The main function that returns value of a given postfix expression 
int evaluatePostfix( char * exp ) 
{ 
     // Create a stack of capacity equal to expression size 
     struct Stack* stack = createStack( strlen ( exp )); 
     int i; 
  
     // See if stack was created successfully 
     if (!stack) return -1; 
  
     // Scan all characters one by one 
     for (i = 0; exp [i]; ++i) 
     { 
         // If the scanned character is an operand (number here), // push it to the stack. 
         if ( isdigit ( exp [i])) 
             push(stack, exp [i] - '0' ); 
  
         // If the scanned character is an operator, pop two 
         // elements from stack apply the operator 
         else
         { 
             int val1 = pop(stack); 
             int val2 = pop(stack); 
             switch ( exp [i]) 
             { 
             case '+' : push(stack, val2 + val1); break ; 
             case '-' : push(stack, val2 - val1); break ; 
             case '*' : push(stack, val2 * val1); break ; 
             case '/' : push(stack, val2/val1); break ; 
             } 
         } 
     } 
     return pop(stack); 
} 
  
// Driver program to test above functions 
int main() 
{ 
     char exp [] = "231*+9-" ; 
     cout<< "postfix evaluation: " << evaluatePostfix( exp ); 
     return 0; 
}

C

// C program to evaluate value of a postfix expression
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
  
// Stack type
struct Stack
{
     int top;
     unsigned capacity;
     int * array;
};
  
// Stack Operations
struct Stack* createStack( unsigned capacity )
{
     struct Stack* stack = ( struct Stack*) malloc ( sizeof ( struct Stack));
  
     if (!stack) return NULL;
  
     stack->top = -1;
     stack->capacity = capacity;
     stack->array = ( int *) malloc (stack->capacity * sizeof ( int ));
  
     if (!stack->array) return NULL;
  
     return stack;
}
  
int isEmpty( struct Stack* stack)
{
     return stack->top == -1 ;
}
  
char peek( struct Stack* stack)
{
     return stack->array[stack->top];
}
  
char pop( struct Stack* stack)
{
     if (!isEmpty(stack))
         return stack->array[stack->top--] ;
     return '$' ;
}
  
void push( struct Stack* stack, char op)
{
     stack->array[++stack->top] = op;
}
  
  
// The main function that returns value of a given postfix expression
int evaluatePostfix( char * exp )
{
     // Create a stack of capacity equal to expression size
     struct Stack* stack = createStack( strlen ( exp ));
     int i;
  
     // See if stack was created successfully
     if (!stack) return -1;
  
     // Scan all characters one by one
     for (i = 0; exp [i]; ++i)
     {
         // If the scanned character is an operand (number here), // push it to the stack.
         if ( isdigit ( exp [i]))
             push(stack, exp [i] - '0' );
  
         // If the scanned character is an operator, pop two
         // elements from stack apply the operator
         else
         {
             int val1 = pop(stack);
             int val2 = pop(stack);
             switch ( exp [i])
             {
             case '+' : push(stack, val2 + val1); break ;
             case '-' : push(stack, val2 - val1); break ;
             case '*' : push(stack, val2 * val1); break ;
             case '/' : push(stack, val2/val1); break ;
             }
         }
     }
     return pop(stack);
}
  
// Driver program to test above functions
int main()
{
     char exp [] = "231*+9-" ;
     printf ( "postfix evaluation: %d" , evaluatePostfix( exp ));
     return 0;
}

Java

// Java proram to evaluate value of a postfix expression
  
import java.util.Stack;
  
public class Test 
{
     // Method to evaluate value of a postfix expression
     static int evaluatePostfix(String exp)
     {
         //create a stack
         Stack<Integer> stack= new Stack<>();
          
         // Scan all characters one by one
         for ( int i= 0 ;i<exp.length();i++)
         {
             char c=exp.charAt(i);
              
             // If the scanned character is an operand (number here), // push it to the stack.
             if (Character.isDigit(c))
             stack.push(c - '0' );
              
             //  If the scanned character is an operator, pop two
             // elements from stack apply the operator
             else
             {
                 int val1 = stack.pop();
                 int val2 = stack.pop();
                  
                 switch (c)
                 {
                     case '+' :
                     stack.push(val2+val1);
                     break ;
                      
                     case '-' :
                     stack.push(val2- val1);
                     break ;
                      
                     case '/' :
                     stack.push(val2/val1);
                     break ;
                      
                     case '*' :
                     stack.push(val2*val1);
                     break ;
               }
             }
         }
         return stack.pop();    
     }
      
     // Driver program to test above functions
     public static void main(String[] args) 
     {
         String exp= "231*+9-" ;
         System.out.println( "postfix evaluation: " +evaluatePostfix(exp));
     }
}
// Contributed by Sumit Ghosh

python

# Python program to evaluate value of a postfix expression
  
# Class to convert the expression
class Evaluate:
      
     # Constructor to initialize the class variables
     def __init__( self , capacity):
         self .top = - 1
         self .capacity = capacity
         # This array is used a stack 
         self .array = []
      
     # check if the stack is empty
     def isEmpty( self ):
         return True if self .top = = - 1 else False
      
     # Return the value of the top of the stack
     def peek( self ):
         return self .array[ - 1 ]
      
     # Pop the element from the stack
     def pop( self ):
         if not self .isEmpty():
             self .top - = 1
             return self .array.pop()
         else :
             return "$"
      
     # Push the element to the stack
     def push( self , op):
         self .top + = 1
         self .array.append(op) 
  
  
     # The main function that converts given infix expression
     # to postfix expression
     def evaluatePostfix( self , exp):
          
         # Iterate over the expression for conversion
         for i in exp:
              
             # If the scanned character is an operand
             # (number here) push it to the stack
             if i.isdigit():
                 self .push(i)
  
             # If the scanned character is an operator, # pop two elements from stack and apply it.
             else :
                 val1 = self .pop()
                 val2 = self .pop()
                 self .push( str ( eval (val2 + i + val1)))
  
         return int ( self .pop())
                  
  
              
# Driver program to test above function
exp = "231*+9-"
obj = Evaluate( len (exp))
print "postfix evaluation: %d" % (obj.evaluatePostfix(exp))
# This code is contributed by Nikhil Kumar Singh(nickzuck_007)

C#

// C# proram to evaluate value of a postfix expression
using System;
using System.Collections;
  
namespace GFG
{
     class Geek
     {
         //Main() method
         static void Main()
         {
             Geek e = new Geek();
             e.v = ( "231*+9-" );
             e.expression();
             Console.WriteLine( "postfix evaluation: " + e.answer);
             Console.Read();
         }
  
         public string v;
         //'v' is variable to store the string value
  
         public string answer;
         Stack i = new Stack();
         //'Stack()' is inbuilt function for namespace 'System.Collections'
  
         public void expression()
         //evaluation method
         {
             int a, b, ans;
             for ( int j = 0; j < v.Length; j++)
             //'v.Length' means length of the string
             {
                 String c = v.Substring(j, 1);
                 if (c.Equals( "*" ))
                 {
                     String sa = (String)i.Pop();
                     String sb = (String)i.Pop();
                     a = Convert.ToInt32(sb);
                     b = Convert.ToInt32(sa);
                     ans = a * b;
                     i.Push(ans.ToString());
  
                 }
                 else if (c.Equals( "/" ))
                 {
                     String sa = (String)i.Pop();
                     String sb = (String)i.Pop();
                     a = Convert.ToInt32(sb);
                     b = Convert.ToInt32(sa);
                     ans = a / b;
                     i.Push(ans.ToString());
                 }
                 else if (c.Equals( "+" ))
                 {
                     String sa = (String)i.Pop();
                     String sb = (String)i.Pop();
                     a = Convert.ToInt32(sb);
                     b = Convert.ToInt32(sa);
                     ans = a + b;
                     i.Push(ans.ToString());
  
                 }
                 else if (c.Equals( "-" ))
                 {
                     String sa = (String)i.Pop();
                     String sb = (String)i.Pop();
                     a = Convert.ToInt32(sb);
                     b = Convert.ToInt32(sa);
                     ans = a - b;
                     i.Push(ans.ToString());
  
                 }
                 else
                 {
                     i.Push(v.Substring(j, 1));
                 }
             }
             answer = (String)i.Pop();
         }
     }
}

输出如下:

postfix evaluation: -4

评估算法的时间复杂度为O(n), 其中n是输入表达式中的字符数。

上述实施方式存在以下局限性。

1)它仅支持4个二进制运算符" +", " *", "-"和" /"。通过添加更多的开关盒, 可以将其扩展为更多的操作员。

2)允许的操作数仅是一位数字操作数。通过在给定表达式的所有元素(运算符和操作数)之间添加空格之类的分隔符, 可以将该程序扩展为多个数字。

下面给出的是扩展程序, 该程序允许具有多个数字的操作数。

C ++

// CPP program to evaluate value of a postfix 
// expression having multiple digit operands 
#include <bits/stdc++.h>
using namespace std;
  
// Stack type 
class Stack 
{ 
     public :
     int top; 
     unsigned capacity; 
     int * array; 
}; 
  
// Stack Operations 
Stack* createStack( unsigned capacity ) 
{ 
     Stack* stack = new Stack();
  
     if (!stack) return NULL; 
  
     stack->top = -1; 
     stack->capacity = capacity; 
     stack->array = new int [(stack->capacity * sizeof ( int ))]; 
  
     if (!stack->array) return NULL; 
  
     return stack; 
} 
  
int isEmpty(Stack* stack) 
{ 
     return stack->top == -1 ; 
} 
  
int peek(Stack* stack) 
{ 
     return stack->array[stack->top]; 
} 
  
int pop(Stack* stack) 
{ 
     if (!isEmpty(stack)) 
         return stack->array[stack->top--] ; 
     return '$' ; 
} 
  
void push(Stack* stack, int op) 
{ 
     stack->array[++stack->top] = op; 
} 
  
  
// The main function that returns value 
// of a given postfix expression 
int evaluatePostfix( char * exp ) 
{ 
     // Create a stack of capacity equal to expression size 
     Stack* stack = createStack( strlen ( exp )); 
     int i; 
  
     // See if stack was created successfully 
     if (!stack) return -1; 
  
     // Scan all characters one by one 
     for (i = 0; exp [i]; ++i) 
     { 
         //if the character is blank space then continue 
         if ( exp [i] == ' ' ) continue ; 
          
         // If the scanned character is an 
         // operand (number here), extract the full number 
         // Push it to the stack. 
         else if ( isdigit ( exp [i])) 
         { 
             int num=0; 
              
             //extract full number 
             while ( isdigit ( exp [i])) 
             { 
             num = num * 10 + ( int )( exp [i] - '0' ); 
                 i++; 
             } 
             i--; 
              
             //push the element in the stack 
             push(stack, num); 
         } 
          
         // If the scanned character is an operator, pop two 
         // elements from stack apply the operator 
         else
         { 
             int val1 = pop(stack); 
             int val2 = pop(stack); 
              
             switch ( exp [i]) 
             { 
             case '+' : push(stack, val2 + val1); break ; 
             case '-' : push(stack, val2 - val1); break ; 
             case '*' : push(stack, val2 * val1); break ; 
             case '/' : push(stack, val2/val1); break ; 
              
             } 
         } 
     } 
     return pop(stack); 
} 
  
// Driver code
int main() 
{ 
     char exp [] = "100 200 + 2 / 5 * 7 +" ; 
     cout << evaluatePostfix( exp ); 
     return 0; 
} 
  
// This code is contributed by rathbhupendra

C

// C program to evaluate value of a postfix
// expression having multiple digit operands
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
  
// Stack type
struct Stack
{
     int top;
     unsigned capacity;
     int * array;
};
  
// Stack Operations
struct Stack* createStack( unsigned capacity )
{
     struct Stack* stack = ( struct Stack*) malloc ( sizeof ( struct Stack));
  
     if (!stack) return NULL;
  
     stack->top = -1;
     stack->capacity = capacity;
     stack->array = ( int *) malloc (stack->capacity * sizeof ( int ));
  
     if (!stack->array) return NULL;
  
     return stack;
}
  
int isEmpty( struct Stack* stack)
{
     return stack->top == -1 ;
}
  
int peek( struct Stack* stack)
{
     return stack->array[stack->top];
}
  
int pop( struct Stack* stack)
{
     if (!isEmpty(stack))
         return stack->array[stack->top--] ;
     return '$' ;
}
  
void push( struct Stack* stack, int op)
{
     stack->array[++stack->top] = op;
}
  
  
// The main function that returns value 
// of a given postfix expression
int evaluatePostfix( char * exp )
{
     // Create a stack of capacity equal to expression size
     struct Stack* stack = createStack( strlen ( exp ));
     int i;
  
     // See if stack was created successfully
     if (!stack) return -1;
  
     // Scan all characters one by one
     for (i = 0; exp [i]; ++i)
     {
         //if the character is blank space then continue
         if ( exp [i]== ' ' ) continue ;
          
         // If the scanned character is an 
         // operand (number here), extract the full number
         // Push it to the stack.
         else if ( isdigit ( exp [i]))
         {
             int num=0;
              
             //extract full number
             while ( isdigit ( exp [i])) 
             {
             num=num*10 + ( int )( exp [i]- '0' );
                 i++;
             }
             i--;
              
             //push the element in the stack
             push(stack, num);
         }
          
         // If the scanned character is an operator, pop two
         // elements from stack apply the operator
         else
         {
             int val1 = pop(stack);
             int val2 = pop(stack);
              
             switch ( exp [i])
             {
             case '+' : push(stack, val2 + val1); break ;
             case '-' : push(stack, val2 - val1); break ;
             case '*' : push(stack, val2 * val1); break ;
             case '/' : push(stack, val2/val1); break ;
              
             }
         }
     }
     return pop(stack);
}
  
// Driver program to test above functions
int main()
{
     char exp [] = "100 200 + 2 / 5 * 7 +" ;
     printf ( "%d" , evaluatePostfix( exp ));
     return 0;
}
  
// This code is contributed by Arnab Kundu

Java

// Java proram to evaluate value of a postfix 
// expression having multiple digit operands
import java.util.Stack;
  
class Test1
{
     // Method to evaluate value of a postfix expression
     static int evaluatePostfix(String exp)
     {
         //create a stack
         Stack<Integer> stack = new Stack<>();
          
         // Scan all characters one by one
         for ( int i = 0 ; i < exp.length(); i++)
         {
             char c = exp.charAt(i);
              
             if (c == ' ' )
             continue ;
              
             // If the scanned character is an operand 
             // (number here), extract the number
             // Push it to the stack.
             else if (Character.isDigit(c))
             {
                 int n = 0 ;
                  
                 //extract the characters and store it in num
                 while (Character.isDigit(c))
                 {
                     n = n* 10 + ( int )(c- '0' );
                     i++;
                     c = exp.charAt(i);
                 }
                 i--;
  
                 //push the number in stack
                 stack.push(n);
             }
              
             // If the scanned character is an operator, pop two
             // elements from stack apply the operator
             else
             {
                 int val1 = stack.pop();
                 int val2 = stack.pop();
                  
                 switch (c)
                 {
                     case '+' :
                     stack.push(val2+val1);
                     break ;
                      
                     case '-' :
                     stack.push(val2- val1);
                     break ;
                      
                     case '/' :
                     stack.push(val2/val1);
                     break ;
                      
                     case '*' :
                     stack.push(val2*val1);
                     break ;
             }
             }
         }
         return stack.pop(); 
     }
      
     // Driver program to test above functions
     public static void main(String[] args) 
     {
         String exp = "100 200 + 2 / 5 * 7 +" ;
         System.out.println(evaluatePostfix(exp));
     }
}
  
// This code is contributed by Arnab Kundu

C#

// C# proram to evaluate value of a postfix 
// expression having multiple digit operands 
using System;
using System.Collections.Generic;
  
class GFG
{
// Method to evaluate value of 
// a postfix expression 
public static int evaluatePostfix( string exp)
{
     // create a stack 
     Stack< int > stack = new Stack< int >();
  
     // Scan all characters one by one 
     for ( int i = 0; i < exp.Length; i++)
     {
         char c = exp[i];
  
         if (c == ' ' )
         {
             continue ;
         }
  
         // If the scanned character is an  
         // operand (number here), extract 
         // the number. Push it to the stack. 
         else if ( char .IsDigit(c))
         {
             int n = 0;
  
             // extract the characters and 
             // store it in num 
             while ( char .IsDigit(c))
             {
                 n = n * 10 + ( int )(c - '0' );
                 i++;
                 c = exp[i];
             }
             i--;
  
             // push the number in stack 
             stack.Push(n);
         }
  
         // If the scanned character is 
         // an operator, pop two elements 
         // from stack apply the operator 
         else
         {
             int val1 = stack.Pop();
             int val2 = stack.Pop();
  
             switch (c)
             {
                 case '+' :
                 stack.Push(val2 + val1);
                 break ;
  
                 case '-' :
                 stack.Push(val2 - val1);
                 break ;
  
                 case '/' :
                 stack.Push(val2 / val1);
                 break ;
  
                 case '*' :
                 stack.Push(val2 * val1);
                 break ;
             }
         }
     }
     return stack.Pop();
}
  
// Driver Code
public static void Main( string [] args)
{
     string exp = "100 200 + 2 / 5 * 7 +" ;
     Console.WriteLine(evaluatePostfix(exp));
}
}
  
// This code is contributed by Shrikant13

python

# Python program to evaluate value of a postfix 
# expression with integers containing multiple digits
  
class evalpostfix:
     def __init__( self ):
         self .stack = []
         self .top = - 1
     def pop( self ):
         if self .top = = - 1 :
             return
         else :
             self .top - = 1
             return self .stack.pop()
     def push( self , i):
         self .top + = 1
         self .stack.append(i)
  
     def centralfunc( self , ab):
         for i in ab:
  
             # if the component of the list is an integer
             try :
                 self .push( int (i))
             # if the component of the list is not an integer, # it must be an operator. Using ValueError, we can 
             # evaluate components of the list other than type int
             except ValueError:
                 val1 = self .pop()
                 val2 = self .pop()
  
                 # switch statement to perform operation
                 switcher = { '+' :val2 + val1, '-' :val2 - val1, '*' :val2 * val1, '/' :val2 / val1, '^' :val2 * * val1}
                 self .push(switcher.get(i))
         return int ( self .pop())
  
str = '100 200 + 2 / 5 * 7 +'
  
# splitting the given string to obtain 
# integers and operators into a list
strconv = str .split( ' ' )
obj = evalpostfix()
print (obj.centralfunc(strconv))
  
# This code is contributed by Amarnath Reddy

输出:

757

参考文献:

http://www.cs.nthu.edu.tw/~wkhon/ds/ds10/tutorial/tutorial2.pdf

如果发现任何不正确的地方, 或者想分享有关上述主题的更多信息, 请发表评论。

木子山

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: