逆波兰表达式(后缀表达式)--栈的应用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shanghx_123/article/details/80086782

1.什么是逆波兰表达式

逆波兰表达式就是将操作符放置在两个操作数的后面,而通常我们所写的表达式都是中缀表达式,因此,逆波兰表达式也叫后缀表达式。看个例子就明白了。

  • 中缀表达式
  12*(3+4)-6+8/2
  • 后缀表达式
 12 3 4 + * 6 - 8 2 / +

2.如何实现

主要思路就是栈的Push和Pop操作,具体看下图;
这里写图片描述

3.代码

具体操作就看代码了;

  1. 先把栈的相关操作给出;

    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.结果
这里写图片描述

猜你喜欢

转载自blog.csdn.net/shanghx_123/article/details/80086782