[Data Structure] - Evaluation of Infix Expression

Keywords: C++ Lambda

Title Requirements

Enter the infix expression from the keyboard, set up the stack of operands and operators, and calculate and output the evaluation results of the expression.
Basic requirements: implement +, -, *, /four binary operators and (); operands range from 0 to 9.
Increased requirements: implement +, - two unary operators (i.e., positive and negative signs); operands can be any integer value (program does not consider calculation overflow).
If two integers are divided, only the integer quotient is preserved (the remainder is discarded); expression syntax errors are not handled.

Involving knowledge points

Stack and Queue

Data structure design

A C++ template class is used to create Operator Stack OPND with integer element type and Operator Stack OPTR with character type. In each stack object, the elem pointer is used to create an array of length n, n is the maximum number of elements in the stack, and top is the top pointer.

Algorithmic Description

1. The infix expression ends with'#', and the'#'character is also used as an operator.
(2)'(','))'is treated as an operator and parentheses need to be removed after the operation in parentheses is completed.
(3) Two different types of stacks need to be built, the integer operand stack OPND and the character operator stack OPTR.
(4) The main steps of the algorithm:
a. Initially, OPND is empty with'#'as the bottom element of the OPTR stack;
b. Read each character in the expression in turn, and if an operand, press directly into the OPND stack;
c. If the operator (denoted as theta), the top operator of the PTR stack (denoted as lambda) takes precedence;
Lambda <theta, theta pushes into the OPTR stack and continues reading the next character;
Lambda=theta, parentheses off, continue reading the next character;
Lambda>theta, performs the lambda operation (lambda de-stacking), theta equals outside the stack (do not read the next character), that is, theta continues to be preferred to the OPTR top operator (repeat the above operation) until theta can be stacked.
For unary operators (positive and negative signs), use'P'for'+','N' for'-'.

Program Code

#include<iostream>
using namespace std;
template <typename T>
class Stack                 //Template class: stack
{
public:
    Stack();                //Default constructor
    Stack(int n);           //Constructor that calls the function createStack(int n) to create a stack of length n
    ~Stack();               //Fictitious function
    int createStack(int n); //Create a stack of length n
    int empty();            //Determine if stack is empty
    int full();             //Determine if the stack is full
    int push(T e);          //Stack element e
    int pop(T &e);          //Element out of stack, saved in e
    T get_top();            //Get the top element of the stack
    friend int isoperator(char &e);//Determine whether character e is an operator
    friend int isp(char &e);//Returns the priority of an operator on the stack
    friend int icp(char &e);//Returns the priority of an out-of-stack operator
    friend int compute(int x, char a, int y);//Evaluation function
private:
    T *elem;                //Create an array of length n
    int n;                  //Maximum number of elements in stack
    int top;                //top of stack
};
template<typename T>
Stack<T>::Stack()
{
    top = -1;
}
template<typename T>
Stack<T>::Stack(int n)
{
    createStack(n);
}
template<typename T>
Stack<T>::~Stack()
{
    n = 0;
    top = -1;
    delete[]elem;
}
template<typename T>
int Stack<T>::createStack(int n)
{
    if (n <= 0)
        return 0;
    this->n = n;
    top = -1;
    elem = new T[n];
    if (!elem)
        return 0;
    return 1;
}
template<typename T>
int Stack<T>::empty()
{
    return top == -1;
}
template<typename T>
int Stack<T>::full()
{
    return top >= n - 1;
}
template<typename T>
int Stack<T>::push(T e)
{
    if (top >= n - 1)
        return 0;
    elem[++top] = e;
    return 1;
}
template<typename T>
int Stack<T>::pop(T & e)
{
    if (top == -1)
        return 0;
    e = elem[top--];
    return 1;
}
template<typename T>
T Stack<T>::get_top()
{
    return elem[top];
};
int isoperator(char &e)        //Determine whether it is an operator
{
    if (e == '+' || e == '-' || e == '*' || e == '/' || e == '(' || e == ')' || e == '#' || e == 'P' || e == 'N')
        return 1;      //Is operator returns 1
    else
        return 0;      //Not an operator returns 0
}
int isp(char &e)               //Returns the priority of an operator on the stack
{
    switch (e)
    {
    case '#':
        return 0; break;
    case '(':
        return 1; break;
    case '+':
    case '-':
        return 2; break;
    case '*':
    case '/':
        return 3; break;
    case 'P':
    case 'N':
        return 4; break;
    case ')':
        return 5; break;
    default:
        return -1; break;
    }
}
int icp(char &e)                 //Returns the priority of an out-of-stack operator
{
    switch (e)
    {
    case '#':
        return 0; break;
    case ')':
        return 1; break;
    case '+':
    case '-':
        return 2; break;
    case '*':
    case '/':
        return 3; break;
    case 'P':
    case 'N':
        return 4; break;
    case '(':
        return 5; break;
    default:
        return -1; break;
    }
}
int compute(int x, char a, int y)
{
    switch (a)
    {
    case '+':                //Calculate Addition
        return x + y; break;
    case '-':                //Calculate Subtraction
        return x - y; break;
    case '*':                //Calculate Multiplication
        return x * y; break;
    case '/':                //Calculate Division
        return x / y; break;
    default:
        return -1; break;
    }
}
int g1()
{
    char a, b, c;
    int i, j, f, value, firstOpnd, secondOpnd, m;
    Stack<char> OPTR(MAX);    //Build Operator Stack
    Stack<int> OPND(MAX);     //Build Operand Stack
    OPTR.push('#');           //'#'Stack
    cout << "Please enter an infix expression: ";
    a = getchar();
    while (a != '#' || OPTR.get_top() != '#')
    {
        if (!isoperator(a))   //Not an operator, that is an operand, operands stacked
            OPND.push(a - 48);//Converting Character Types to Integer Numbers
        else                  //Is an operator that compares the priority size to the top stack operator
        {
            b = OPTR.get_top();//Get the top element of the stack
            i = isp(b);       //Priority of stack top operator
            j = icp(a);       //Priority of off-stack operators
            if (i < j)        //Out-of-stack operators have high priority and operators are stacked
                OPTR.push(a);
            else
            {
                OPTR.pop(b);                    
                if (b != '('&&i == j || i > j)
                {
                    c = OPTR.get_top();
                    if ((c == '(' || c == '#') & && (b =='P'|| B =='N') /*c is unary
                                                                            Operator: Positive and negative sign*/
                    {
                        OPND.pop(firstOpnd); //Get Operand
                        switch (b)
                        {
                        case 'P':            //Positive sign
                            f = firstOpnd * 1;
                            break;
                        case 'N':            //Minus sign
                            f = firstOpnd * (-1);
                            break;
                        }
                    }
                    else                     //c is a binary operator
                    {
                        OPND.pop(secondOpnd); //Get the second operand
                        OPND.pop(firstOpnd);  //Get the first operand
                        f = compute(firstOpnd, b, secondOpnd); //Calculate Evaluation
                    }
                    OPND.push(f);             //Evaluation Result Stack
                    continue;
                }
            }
        }
        c = a;
        a = getchar();                         //Continue reading characters
        while(!isoperator(a) && !isoperator(c))  /*Multiply the bit weight if the continuous read characters are all numbers
                                                  Get multidigits*/
        {
            OPND.pop(m);
            m = m * 10 + a - 48;
            OPND.push(m);
            c = a;
            a = getchar();
        }
        
    }
    OPND.pop(value);
    return value;      //Returns the result of an expression
}
int main()
{
    int a;
    a = g1();
    cout << "The result of the operation is:  " << a << endl;
    return 0;
}

Example

(1) Program input: 3+5* (9-5)/10#
Program Output: 5

(2) Program input: P9+10*(N2*8/4)-10#
Program Output: -41

(3) Program input: 20-3*25+(N41/3)*100#
Program Output: -1355

Posted by amir on Fri, 05 Jun 2020 19:18:06 -0700