1.什么是逆波兰表达式
逆波兰表达式就是将操作符放置在两个操作数的后面,而通常我们所写的表达式都是中缀表达式,因此,逆波兰表达式也叫后缀表达式。看个例子就明白了。
- 中缀表达式
12*(3+4)-6+8/2
- 后缀表达式
12 3 4 + * 6 - 8 2 / +
2.如何实现
主要思路就是栈的Push和Pop操作,具体看下图;
3.代码
具体操作就看代码了;
先把栈的相关操作给出;
Stack.h
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int DataType;
#define MAX_SIZE 100
typedef struct Stack
{
DataType *_array;
int capacity;
int _top;
}Stack;
void StackInit(Stack* s,int capacity);// 栈的初始化
void StackPush(Stack* s, DataType data);// 入栈
void StackPop(Stack* s);// 出栈
DataType StackTop(Stack* s);// 获取栈顶元素
int StackSize(Stack* s);// 获取栈中元素个数
int StackEmpty(Stack* s);// 检测栈是否为空
2.栈的功能函数实现部分
Stack.c
#include"Stack.h"
//非接口函数声明
void AddCapacity(Stack *s);//扩容函数
void PrintStack(Stack *s);//打印栈的元素
void AddCapacity(Stack *s)
{
s->_array= (DataType*)realloc(s->_array, sizeof(DataType) * s->capacity * 2);
if (s->_array == NULL)
{
printf("空间申请失败!!!\n");
return;
}
s->capacity = s->capacity * 2;
return;
}
void StackInit(Stack* s,int capacity)// 栈的初始化
{
assert(s);
s->_array= (DataType*)malloc(sizeof(DataType) * capacity);
if (s->_array == NULL)
{
printf("空间申请失败!!!\n");
return;
}
s->capacity = capacity;
s->_top = 0;
}
void StackPush(Stack* s, DataType data)// 入栈
{
assert(s);
if (s->_top == s->capacity)
{
AddCapacity(s);
}
s->_array[s->_top] = data;
s->_top++;
}
void StackPop(Stack* s)// 出栈
{
assert(s);
if (s->_top == 0)
{
printf("栈空,无法出栈!!!\n");
return;
}
s->_top--;
}
DataType StackTop(Stack* s)// 获取栈顶元素
{
assert(s);
return s->_array[s->_top - 1];
}
int StackSize(Stack* s)// 获取栈中元素个数
{
assert(s);
return s->_top;
}
int StackEmpty(Stack* s)// 检测栈是否为空
{
assert(s);
if (s->_top == 0)
return 1;
else return 0;
}
void PrintStack(Stack *s)
{
assert(s);
while (s->_top)
{
printf("%d ", s->_array[s->_top-1]);
s->_top--;
}
printf("\n" );
return;
}
3.下面的函数是求逆波兰表达式
PostfixExpression.c
#include"Stack.h"
void PostfixExpression(const char *str)
{
Stack s; //定义一个栈用来保存数据
StackInit(&s, 100); //这块是重点,初始化不能忘记(因为栈是动态栈,初始化栈才会给詹=栈开辟空间)
//i时循环变量,data是每次字符转化后的数字,sum是表达式中的数,result是两数计算后的结果
int i = 0,data=0,sum=0,result=0;
//两个操作数
int count1 = 0, count2 = 0;
//判断字符串是否为空
if (str == NULL)
return;
//实现部分
while (str[i] != '\0')
{
//如果是一个数字字符,进入循环
if (str[i] >= '0'&&str[i] <= '9')
{
sum = 0;//每次进入循环前赋初值
while (str[i] != ' ')
{
//转换每个字符为数字
data = str[i] - '0';
sum = data + sum * 10;
i++;//之后指针后移
}
//循环跳出说明当前字符是空格,并且它的前一个字符一定是数字字符,此时就可以把当前sum的值压入栈中
StackPush(&s, sum);
i++;//指针后移到下个字符
}
else
//如果不是字符,那么只有是操作符或者是空格了,并且如果是空格,该空格前一个字符一定是操作符
if(str[i]=='+'|| str[i] == '-' || str[i] == '*' || str[i] == '/' )
{
//分别取栈中的两个操作数,并且出栈
count2= StackTop(&s);StackPop(&s);
count1 = StackTop(&s); StackPop(&s);
//执行不同的算术操作
switch (str[i])
{
case '+':
{
result = count1 + count2;//得到结果之后压栈
StackPush(&s, result);
i++; continue;//指针再后移
}
//下同
case '-':
{
result = count1 - count2;
StackPush(&s, result);
i++; continue;
}
case '*':
{
result = count1 * count2;
StackPush(&s, result);
i++; continue;
}
case '/':
{
if (count2 == 0)return;
result = count1 / count2;
StackPush(&s, result);
i++; continue;
}
}
}
//运行到这一步,就只有一种可能,当前字符是空格,并且它前一个字符一定是操作数,此时只需要指针后移即可
else i++;
}
//外层循环跳出,该字符串读取结束,打印当前栈顶的值即可
printf("%d\n", StackTop(&s));
return;
}
4.测试
test.c
#include"Stack.h"
int main()
{
char str[] = "12 3 4 + * 6 - 8 2 / +";
PostfixExpression(&str);
system("pause");
return 0;
}
5.结果