Stacks and Queues of Data Structure Exercises: Converting Arithmetic Expressions to Postfix Expressions (C language implementation)

content

I. Introduction

2. Problem Analysis

3. Example application - general arithmetic expressions are converted into suffix expressions

(1) Definition of the basic operation functions of the stack

(2) Main function

(3) Operation result

 (4), complete code

(5) Summary


I. Introduction:

       It took a day to implement this function with code. The process was very painful, and there were many errors. Maybe I was relatively good, and it took a day to debug it. As the saying goes: making mistakes is the beginning of self-improvement. If there is no error, then the problem will never be found. Only through the occurrence of the problem, the analysis of the problem, and the solution of the problem can you gain something and improve. The process is difficult, but the moment the problem is solved, it is like winning a lottery Same. Converting arithmetic expressions to postfix expressions is a classic application of stacks. The idea is the same, mastering this idea, all arithmetic expressions can be converted into suffix expressions using this idea, and the code is universal.

Please indicate the link of this article when reprinting!

Second, the problem analysis:

       What is an arithmetic expression: it is the expression of the mathematical problems we usually do, such as: a*b+(cd/e)*f

       What is a suffix expression: put the operator after the operand, the suffix expression corresponding to the above formula is: ab*cde/-f*+, the operator in front is executed first. Otherwise the relative order of operands is unchanged, and parentheses are not included in postfix expressions.

        We have to analyze how to set the conditions so that the computer can understand our thoughts and what we want the computer to do. We can see some things at a glance, but the computer needs us to convey instructions to it before it can follow us. ideas to work.

        For the stack, we must first know that the stack is a first-in-last-out array, and only pop and push operations are allowed at the top of the stack. Arrays must have a size, we can first define an array large enough to store our input arithmetic expressions. Then define a stack structure, a stack S1 is used to store the final suffix expression, the location of the stack S1 is the reverse order of the suffix expression, we can use an array to get the elements of this stack S1, when outputting, from The last bit can be output forward. Why use the stack S1 to store the suffix expression instead of the array? Because the stack is very convenient to operate, you only need to call functions such as popping the stack and pushing the stack. Of course, you can also use an array direct storage. Another stack S2 is used to store the operators in the arithmetic expression, and the operator that pops the stack first executes the operation first! Therefore, we need to set some conditions to determine when the operator in S2 is popped off the stack, and when the currently scanned operator is pushed onto the stack. 

        Scan the current arithmetic expression to get the current character C: There are the following rules for popping into the stack:

(1) If c='(' the left bracket, directly store it in the stack S2 of the postfix expression.

        //如果是左括号,直接进栈
        if(c=='(')
        {
            Push(&S2,c);
        }

(2) If c=')' close bracket, we get the top element of the stack S2 of the current storage operator, if it is not equal to the left bracket '(', the stack top element of stack S2 is advanced to S1, Then S2 performs the pop-out operation, then obtains the top element of the stack S2 again, continues to perform the step (2), and executes the loop. Until the '(' left parenthesis is encountered for the first time, the loop is stopped, and the '(' is removed from S2 Just pop it from the stack and continue to scan the next character of the arithmetic expression.

        else if(c==')')
        {
            char b=Get(S2);//获取存操作符的栈顶元素
            while(b!='(')//遇见左括号之前一直循环出栈S2
            {
                Push(&S1,b);//存入到栈S1
                Pop(&S2);    //进行出栈S2
                b=Get(S2);//再获取栈顶S2的元素
                //printf("--------++%c\n",b);
            }
            Pop(&S2);

(3) If c!='+' and c!='-' and c!='*' and c!='/' and c!=')'. Then we store it directly into the stack S1 of the postfix expression. Here it can be understood that c is a number or c is a series of unknown variables x. Continue to scan the next character of the arithmetic expression.

        else if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!=')')//根据题目变换
        {
            Push(&S1,c);
        }

(4) If c=='+' or c=='-', that is, we have now encountered the two operators of addition and subtraction, we first judge whether the stack S2 is an empty stack, if it is an empty stack, Then we can directly put the current operator c into the stack S2. If it is not empty, we get what is the top element of stack S2. If it is a left bracket '(', then we can directly put the current operator c into the stack S2; if it is not a left bracket '(', then we will stack the top element of the stack S2 into S1 first, and then Let S2 perform the pop operation, and then obtain the top element of the stack S2 again, and execute this step (4) in a loop, until the '(' left parenthesis is encountered for the first time, or the stack is empty, the loop is stopped, and the '(' Just pop the stack from S2 and continue to scan the next character of the arithmetic expression. If the left bracket is not encountered, then we keep popping the stack until the stack is empty, and then push c into the stack S2. Continue to scan the arithmetic expression the next character of the formula.

        else if(c=='+'||c=='-')
        {
            if(S2.top==-1)         //如果操作符栈为空,直接进栈
            {
                Push(&S2,c);
            }
            else
            {
                b=Get(S2);
                while(b!='(')         //只要不为左括号或者是栈不为空,那就一直出栈
                {
                    Push(&S1,b);         //运算符存入到栈S1中
                    Pop(&S2);
                    if(S2.top!=-1)            //栈不为空,执行一次出栈
                    {
                        b=Get(S2);           //再获取栈顶
                    }
                    else
                    {
                        break;
                    }
                }
                Push(&S2,c);
            }

        }

(5) If c=='*'||c=='/', that is, we have encountered the two operators of multiplication and division, we first judge whether the stack S2 is an empty stack, if it is an empty stack, we Simply put the current operator c into the stack S2. If it is not empty, we get the top element of the stack S2, if b!='(' and b!='+' and b!='-', here is used and, not used or, i Here is a problem. Only when it is not for these three, it is true at the same time. We push the top element of the current S2 into the stack S1, then the stack S2 performs the pop operation, and then obtains the stack of the stack S2 again. The top element, repeat (5), until the stack is empty or the top element of the stack is equal to one of the three above, we stop the loop and put the current operator c into the stack S2. Continue to scan the arithmetic expression the next character.

    else if(c=='*'||c=='/')
        {
            if(S2.top==-1)
            {
               Push(&S2,c);
            }
            else
            {
                b=Get(S2);
                while(b!='('&&b!='+'&&b!='-')
                {
                    Push(&S1,b);          //运算符存入到栈S1中
                    Pop(&S2);
                    if(S2.top!=-1)             //执行一次出栈
                    {
                       b=Get(S2);
                    }
                    else
                    {
                        break;
                    }
                }
                Push(&S2,c);
            }
        }

(6) When the array of arithmetic expressions is scanned, the operators stored in stack S2 are popped out of the stack and entered into stack S1 in turn. At this time, the order in stack S1 is the reverse order of the suffix expression we require. We Store this reverse order into an array, and reverse the output of this array is the suffix expression we require.

    while(S2.top!=-1)      //将S2中剩余的操作符存入到栈S1中
    {
        char c=Get(S2);
        Push(&S1,c);
        Pop(&S2);
    }
    int a=S1.top;           //记录后缀表达式的长度
    for(int i=0;S1.data[S1.top]!=-1;i++)   //将栈S1中的元素存入到数组中
    {
        data1[i]=S1.data[S1.top];
        S1.top--;
    }
    for(int i=a;i>=0;i--)             //反向输出数组即可
    {
        printf("%c",data1[i]);
    }

The following figure is the steps given in Li Chunbao's book to convert arithmetic expressions into suffix expressions: you can understand mine or understand the following picture.

3. Example application - general arithmetic expressions are converted into suffix expressions

Description

For an arithmetic expression based on a binary operator, convert it to the corresponding postfix expression and output it.

Input

Enter an arithmetic expression, terminated by the '#' character.

Output

Output the postfix expression obtained by converting the expression.

Sample

Input 

a*b+(c-d/e)*f#

Output 

ab*cde/-f*+

(1) Definition of the basic operation functions of the stack

//定义一个栈结构体
typedef struct
{
    char data[Maxsize];    //存储元素
    int top;                //栈顶标记位
}Stack;
//初始化
void Init(Stack *L)
{
    L->top=-1;
}
//进栈操作
void Push(Stack *L,char x)
{
    if(L->top>=Maxsize)//判断是否栈满
    {
        return;
    }
    L->top++;
    L->data[L->top]=x;      //栈没满就将x入栈
}
//出栈操作
void Pop(Stack *L)
{
    if(L->top==-1)//判断是否为空
    {
        return;
    }
    L->top--;        //不空就将栈顶标记位减一
}
//获取栈顶元素
char Get(Stack L)
{
    if(L.top==-1)
    {
        return 0;
    }
    else
    {
        return L.data[L.top];
    }
}

(2) Main function

The meaning of the code block in the main function has been introduced in detail in the second part of the problem analysis. You can gather this code to understand those words, and the logic is very simple.

int main()
{
    Stack S1;//存放最终的表达式
    Stack S2;//存放运算符
    Init(&S1);
    Init(&S2);
    char data[Maxsize];//存放用户输入的表达式
    scanf("%s",data);
    char data1[Maxsize];
    char b;
    for(int i=0;data[i]!='#';i++)
    {
        char c=data[i];
        if(c=='(')
        {
            Push(&S2,c);
        }
        else if(c==')')
        {
            char b=Get(S2);//获取存操作符的栈顶元素
            while(b!='(')//遇见左括号之前一直循环出栈S2
            {
                Push(&S1,b);//存入到栈S1
                Pop(&S2);    //进行出栈S2
                b=Get(S2);//再获取栈顶S2的元素
            }
            Pop(&S2);
        }
        else if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!=')')//根据题目变换
        {
            Push(&S1,c);
        }
        else if(c=='+'||c=='-')
        {
            if(S2.top==-1)         //如果操作符栈为空,直接进栈
            {
                Push(&S2,c);
            }
            else
            {
                b=Get(S2);
                while(b!='(')         //只要不为左括号或者是栈不为空,那就一直出栈
                {
                    Push(&S1,b);         //运算符存入到栈S1中
                    Pop(&S2);
                    if(S2.top!=-1)            //栈不为空,执行一次出栈
                    {
                        b=Get(S2);           //再获取栈顶
                    }
                    else
                    {
                        break;
                    }
                }
                Push(&S2,c);
            }

        }
        else if(c=='*'||c=='/')
        {
            if(S2.top==-1)
            {
               Push(&S2,c);
            }
            else
            {
                b=Get(S2);
                while(b!='('&&b!='+'&&b!='-')
                {
                    Push(&S1,b);          //运算符存入到栈S1中
                    Pop(&S2);
                    if(S2.top!=-1)             //执行一次出栈
                    {
                       b=Get(S2);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
    }
    while(S2.top!=-1)
    {
        char c=Get(S2);
        Push(&S1,c);
        Pop(&S2);
    }
    int a=S1.top;
    for(int i=0;S1.data[S1.top]!=-1;i++)
    {
        data1[i]=S1.data[S1.top];
        S1.top--;
    }
    for(int i=a;i>=0;i--)
    {
        printf("%c",data1[i]);
    }
    return 0;
}

(3) Operation result

 (4), complete code

#include <stdio.h>
#include <stdlib.h>
#define Maxsize 1000
//定义一个栈结构体
typedef struct
{
    char data[Maxsize];    //存储元素
    int top;                //栈顶标记位
}Stack;
//初始化
void Init(Stack *L)
{
    L->top=-1;
}
//进栈操作
void Push(Stack *L,char x)
{
    if(L->top>=Maxsize)//判断是否栈满
    {
        return;
    }
    L->top++;
    L->data[L->top]=x;      //栈没满就将x入栈
}
//出栈操作
void Pop(Stack *L)
{
    if(L->top==-1)//判断是否为空
    {
        return;
    }
    L->top--;        //不空就将栈顶标记位减一
}
//获取栈顶元素
char Get(Stack L)
{
    if(L.top==-1)
    {
        return 0;
    }
    else
    {
        return L.data[L.top];
    }
}
int main()
{
    Stack S1;//存放最终的表达式
    Stack S2;//存放运算符
    Init(&S1);
    Init(&S2);
    char data[Maxsize];//存放用户输入的表达式
    scanf("%s",data);
    char data1[Maxsize];
    char b;
    for(int i=0;data[i]!='#';i++)
    {
        char c=data[i];
        if(c=='(')
        {
            Push(&S2,c);
        }
        else if(c==')')
        {
            char b=Get(S2);//获取存操作符的栈顶元素
            while(b!='(')//遇见左括号之前一直循环出栈S2
            {
                Push(&S1,b);//存入到栈S1
                Pop(&S2);    //进行出栈S2
                b=Get(S2);//再获取栈顶S2的元素
            }
            Pop(&S2);
        }
        else if(c!='+'&&c!='-'&&c!='*'&&c!='/'&&c!=')')//根据题目变换
        {
            Push(&S1,c);
        }
        else if(c=='+'||c=='-')
        {
            if(S2.top==-1)         //如果操作符栈为空,直接进栈
            {
                Push(&S2,c);
            }
            else
            {
                b=Get(S2);
                while(b!='(')         //只要不为左括号或者是栈不为空,那就一直出栈
                {
                    Push(&S1,b);         //运算符存入到栈S1中
                    Pop(&S2);
                    if(S2.top!=-1)            //栈不为空,执行一次出栈
                    {
                        b=Get(S2);           //再获取栈顶
                    }
                    else
                    {
                        break;
                    }
                }
                Push(&S2,c);
            }

        }
        else if(c=='*'||c=='/')
        {
            if(S2.top==-1)
            {
               Push(&S2,c);
            }
            else
            {
                b=Get(S2);
                while(b!='('&&b!='+'&&b!='-')
                {
                    Push(&S1,b);          //运算符存入到栈S1中
                    Pop(&S2);
                    if(S2.top!=-1)             //执行一次出栈
                    {
                       b=Get(S2);
                    }
                    else
                    {
                        break;
                    }
                }
            }
        }
    }
    while(S2.top!=-1)
    {
        char c=Get(S2);
        Push(&S1,c);
        Pop(&S2);
    }
    int a=S1.top;
    for(int i=0;S1.data[S1.top]!=-1;i++)
    {
        data1[i]=S1.data[S1.top];
        S1.top--;
    }
    for(int i=a;i>=0;i--)
    {
        printf("%c",data1[i]);
    }
    return 0;
}

(5) Summary

        This question took me a day. I really debugged it bit by bit. I added a print statement to each condition to see which condition went wrong, and finally determined that the problem occurred in When c=* or c=/ this judgment, when scanning to this, we should define this b!='('&&b!='+'&&b!='-' condition, not b!='( '||b!='+'||b!='-', because && means that all true is true, and || means that as long as one is true, it is true, and the conditions in the condition will be executed. Loop body. For example, let's take an example: a+(b*c+d)#, when we scan to the closing bracket), if we use b!='('||b!='+'|| The condition of b!='-', when we scan to the * sign, we reach the left parenthesis b=( at the top of the operator stack, then we use b!='('||b!='+'| When |b!='-' is used as a condition, this condition is true, because b is not equal to +, - at this time. So the content inside will be executed. But what we want to express is when b=(, we directly Push * onto the stack, not pop it.

        Although I did this question today, it really made me work hard and gain something. When setting the judgment conditions, we must consider both the positive and negative sides. Only when the conditions are set correctly can our program be executed according to what we want it to be. direction to execute. come on!

Guess you like

Origin blog.csdn.net/BaoITcore/article/details/121456313