Convert infix expression to postfix expression and calculate, implemented in C language

insert image description here

Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right


foreword

As the most familiar expression 1+1, do you know that it is also called infix expression?


1. Infix expression? postfix expression?

  • Infix expressions
    Infix expressions are actually arithmetic expressions commonly used in our daily life, such as 1+2+3, 1+2x3 and so on. So how do we calculate it?
    For 1+2+3, because + and - have the same priority, we generally perform addition calculations from left to right.
    For 1+2x3, because the priority of x is greater than +, we perform multiplication first and then addition.
    In our eyes, such an infix expression (the operator is in the middle, and the operands are on both sides) is very easy to calculate. We know at a glance (when the expression is not very complicated), which step should be calculated, and which step should be calculated later. But for computers, when dealing with infix expressions, they can only traverse the expressions over and over again, and perform calculations according to the priority of operators. This is too inefficient, so there is a suffix expression (reverse Polish expression).
  • Postfix expressions
    We call operands first and operators after expressions postfix expressions.
    as follows:
    insert image description here

So how is it converted?
1. Determine the order of operation of the operators in the infix expression
2. Select the operator with the highest priority, with (operand operand operator) [the first operand is the left side of the operator, the second operand is The form of ] on the right side of the operator forms a new operand.
Repeat the above operations until all operators are sorted.
As follows:
insert image description here
Now that we know how to convert an infix expression to a postfix expression, how to calculate the postfix expression?
As follows:
insert image description here
We will find that calculating the suffix expression does not need to consider the order of operations of the operators. It only needs to traverse from left to right, and execute the corresponding operation when encountering an operator. So how to achieve it with code?

2. Implementation ideas

We use the stack structure to achieve the following two problems.

1. Infix expression to postfix expression

We use a stack (s2) to store operators whose order of operation cannot be determined, and a stack (s1) [of course, an array can also be used] to store strings whose order is determined.

  • When an operand is encountered, it is directly pushed into s1.
  • When an operator is encountered, if s2 is an empty stack, push it directly to the stack; if not, judge whether the priority of the operator on the top of the stack is greater than or equal to the operator. If the priority is greater than or equal to the operator, then pop the top element of the stack and continue to judge The priority of the top element of the stack. Repeat this process until the priority of the operator at the top of the stack is lower than the operator or s2 is empty, then push the operator directly onto the stack.
  • Encountered ' ( ' directly pushed into s2.
  • Encounter ' ) ', start popping the top element in s2, push it into s1, until the top element of the stack is ' ( ', pop the character.
  • If the traversal of the infix expression is complete, then directly push all the elements in s2 into s1.

as follows:
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

insert image description here
insert image description here
insert image description here

2. Calculate postfix expression

We create a stack (numsStack) to store the calculation results.
Read the suffix expressions directly in order from left to right

  • When an operand is encountered, it is directly pushed onto the stack
  • When an operator is encountered, pop the top element of the stack as the left operand, and pop the top element of the stack again as the right operand. Let the two operands perform the corresponding operation, and push the operation result as a new operand on the stack

Repeat the above two steps, and finally there will be only one element in the stack (numsStack), which is the result of the operation.

3. Code implementation

Here I use Stack.h to store the creation of the stack structure, the statement about the operation of the stack function, and the reference of the header file. Stack.c stores the implementation of stack-related functions. test.c stores the implementation of infix expression conversion postfix expression and calculation

Stack.h

#pragma once

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>

#define MaxSize 10
#define MaxString 100

typedef char STDataType;
typedef struct Stack
{
    
    
	STDataType* a;
	int top;
	int capacity;
}ST;

//初始化
void StackInit(ST* ps);

//销毁
void StackDestroy(ST* ps);

//压栈
void StackPush(ST* ps, STDataType x);

//弹栈
void StackPop(ST* ps);

//读取栈顶元素
STDataType StackTop(ST* ps);

//读取栈中元素个数
int StackSize(ST* ps);

//判空
bool StackEmpty(ST* ps);

Stack.c

#include "stack.h"

//
void StackInit(ST* ps)
{
    
    
	ps->a = (STDataType*)malloc(sizeof(STDataType) * (MaxSize));
	ps->capacity = MaxSize;
	ps->top = 0;
}

//
void StackPush(ST* ps, STDataType x)
{
    
    
	if (ps->capacity == ps->top)
	{
    
    
		ps->a = (STDataType*)realloc(ps->a, sizeof(STDataType)*(2 * ps->capacity));
		ps->capacity *= 2;
		if (ps->a == NULL)
		{
    
    
			return;
		}
	}

	ps->a[ps->top] = x;
	ps->top++;
}


//
void StackPop(ST* ps)
{
    
    
	if (ps->top == 0)
	{
    
    
		return;
	}

	ps->top--;
}

//
STDataType StackTop(ST* ps)
{
    
    
	STDataType x = ps->a[ps->top - 1];

	return x;
}

//
void StackDestroy(ST* ps)
{
    
    
	if (ps->a)
	{
    
    
		free(ps->a);
		ps->a = NULL;
		ps->capacity = 0;
		ps->top = 0;
	}
}

//
int StackSize(ST* ps)
{
    
    
	return ps->top;
}

//
bool StackEmpty(ST* ps)
{
    
    
	return (ps->top == 0);
}

test.c

#include "stack.h"

//只能进行个位数的中缀转后缀并计算,因为数字10,是字符1和字符0的组合

//直接顺序读取,遇到数字压栈,遇到操作符,pop前两个数字并进行相关计算,再将计算结果压栈

int calPostfix(char* str)
{
    
    
	ST numsStack;
	StackInit(&numsStack);

	for (int i = 0; i < (int)strlen(str); i++)
	{
    
    
		if (str[i] >= '0' && str[i] <= '9')
		{
    
    
			int x = str[i] - '0';
			StackPush(&numsStack, x);
		}
		else
		{
    
    	
			//x右操作数
			int x = StackTop(&numsStack);
			StackPop(&numsStack);
			//y左操作数
			int y = StackTop(&numsStack);
			StackPop(&numsStack);

			switch (str[i])
			{
    
    
				case '+':
					y += x;
					break;
				case '-':
					y -= x;
					break;
				case '*':
					y *= x;
					break;
				case '/':
					y /= x;
					break;
			}

			StackPush(&numsStack, y);
		}
	}

	return StackTop(&numsStack);
}


//假定+,-的优先级是1, *,/的优先级是2,数字是-1 
int compare(char ch)
{
    
    
	if (ch == '+' || ch == '-')
	{
    
    
		return 1;
	}
	else if (ch == '*' || ch == '/')
	{
    
    
		return 2;
	}
	else if (ch == '(' || ch == ')')
	{
    
    
		return 0;
	}
	else
	{
    
    
		return -1;
	}
}


//转换为后缀表达式
//s1保存结果,s2临时保存操作符(优先级)
//遇到数字,直接保存到s1中
// 遇到操作符,如果此时s2为空,则直接push进s1中,否则比较s2中top处操作符优先级与此操作符的优先级
// 如果top优先级大于和等于,再看s2下一个操作符。
// 如果top优先级小于,将该操作符直接push进s2.
//
char* postfixNotation(char* str)
{
    
    
	//s1保存结果,s2临时保存操作符
	ST s1;
	ST s2;
	StackInit(&s1);
	StackInit(&s2);

	for (int i = 0; i < (int)strlen(str); i++)
	{
    
    
		if (compare(str[i]) == -1)
		{
    
    
			StackPush(&s1, str[i]);
		}
		else if (str[i] == '(')
		{
    
    
			StackPush(&s2, str[i]);
		}
		else if (str[i] == ')')
		{
    
    
			while (StackTop(&s2) != '(')
			{
    
    
				char x = StackTop(&s2);
				StackPush(&s1, x);
				StackPop(&s2);
			}
			StackPop(&s2);
		}
		else
		{
    
    
			if (!StackEmpty(&s2) && compare(StackTop(&s2)) >= compare(str[i]))
			{
    
    
				while (!StackEmpty(&s2) && compare(StackTop(&s2)) >= compare(str[i]))
				{
    
    
					char x = StackTop(&s2);
					StackPop(&s2);
					StackPush(&s1, x);
				}
				StackPush(&s2, str[i]);
			}
			else
			{
    
    
				StackPush(&s2, str[i]);
			}
		}
	}
	while (!StackEmpty(&s2))
	{
    
    
		char x = StackTop(&s2);
		StackPush(&s1, x);
		StackPop(&s2);
	}
	StackPush(&s1, '\0');

	return (char*)s1.a;
}

int main()
{
    
    
	char str[MaxString];
	gets(str);

	strcpy(str, postfixNotation(str));
	printf("%s\n", str);

	int ret = calPostfix(str);
	printf("%d\n", ret);

	return 0;
}

Summarize

The above is my understanding of converting infix expressions to postfix expressions. If there is a problem with that step, thank you guys for pointing it out! ! !
Finally, thanks for watching! ! !
insert image description here

Guess you like

Origin blog.csdn.net/li209779/article/details/131178517