反波兰表达式的转化和计算·示例代码

一、反波兰表达式的转化方法

1.设定运算符栈;

2.从左到右遍历中缀表达式的每个数字和运算符;

3.若当前字符是数字,则直接输出成为后缀表达式的一部分;

4.若当前字符为运算符,则判断其与栈顶运算符的优先级,若优先级大于栈顶运算符,则进栈;若优先级小于等于栈顶运算符,退出栈顶运算符成为后缀表达式的一部分,然后将当前运算符放入栈中,注意,这一步需要重复进行直到当前字符大于栈顶运算符;

5.若当前字符为“(”,进栈;

6.若当前字符为“)”,则从栈顶起,依次将栈中运算符出栈成为后缀表达式的一部分,直到碰到“(”。将栈中“(”出栈,不需要成为后缀表达式的一部分,然后继续扫描表达式直到最终输出后缀表达式为止。

7.最后要把栈中剩余的运算符按顺序全部弹出,加入到后缀表达式!!!

————————————————

版权声明:本文为CSDN博主「JAZHR」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_43290883/article/details/125633103

二、反波兰表达式的转化·示例代码

该段代码用于将中缀表达式转化为后缀表达式

#include 
#include  
#define MAXSIZE_signStack 100
#define MAXSIZE_INPUT  1000
#define MAXSIZE_OUTPUT 1000

//中缀转后缀函数 
char signStack[MAXSIZE_signStack]; //操作符栈 
int signtop;   //操作符栈栈顶编号

char input[MAXSIZE_INPUT];     //中缀表达式 
char output[MAXSIZE_OUTPUT];   //后缀表达式 

//中缀转后缀函数以及其附属函数声明

//中缀表达式必须严格存储在input数组中
//后缀表达式必须严格存储在output数组中
//上述两数组的最大值由MAXSIZE_INPUT和MAXSIZE_OUTPUT定义,需要进行define
//需要定义操作符栈数组和操作符栈栈顶编号 
void anti_poland_tras(); 
void initStack(int* ptop); 
int isEmpty(int* ptop);
int isFull(int* ptop);
void Error(char *s);
void push_char(char *s,char item,int* ptop);
void pop_char(int* ptop);
int grade(char a);
//栈空判断函数和满栈判断函数可能与其它功能重复,请小心使用 

int main(void)
{
    //获取中缀表达式
    gets(input); 
    
    //进行转化为反波兰表达式的运算 
    anti_poland_tras();
    
    puts(output);    
}

//中缀转后缀函数 
void anti_poland_tras()
{
    //设定运算符栈
    initStack(&signtop);
    
    //操作符栈栈底以'#'垫底
    push_char(signStack,'#',&signtop);
    
    //遍历中缀表达式 
    int i;
    int j=0;
    //j用于记录output数组的长度-1 
    
    for (i=0;i='0'&&input[i]<='9')
        {
            //若当前字符为数字,则直接输出为后缀表达式 
            output[j++]=input[i]; 
        }
        else if (input[i]==' ')
        {
            //跳过潜在的空格 
            continue;
        }
        else if (input[i]=='(')
        {
            //如果是左引号,直接进栈 
            push_char(signStack,'(',&signtop);
            //读取符号要间隔
            output[j++]=' '; 
        }
        else if (input[i]==')')
        {
            //从栈顶起,依次将运算符出栈后成为后缀表达式的一部分,直到碰到'('。 
            while(signStack[signtop]!='(')
            {
                output[j++]=signStack[signtop];
                
                pop_char(&signtop);
            }     
            //'('出栈,但不写入后缀表达式 
            pop_char(&signtop);
            //读取符号要间隔
            output[j++]=' '; 
        }
        else
        {
            //当前字符优先级小于等于栈顶运算符,弹出栈顶运算符并输入至后缀表达式
            //重复此操作,直到当前字符优先级大于栈顶运算符 
            while(grade(input[i])<=grade(signStack[signtop]))
            {
                output[j++]=signStack[signtop]; 
                
                pop_char(&signtop);    
            }
            
            //当前字符优先级大于栈顶运算符,当前字符直接进栈 
            push_char(signStack,input[i],&signtop);
            //读取符号要间隔
            output[j++]=' '; 
        }
    }
    
    //最后弹出所有的剩余操作符 
    while (signtop>0)
    {
        output[j++]=signStack[signtop];
     
        pop_char(&signtop);
    }
} 

//建栈函数,参数是指向操作符栈顶编号的指针
void initStack(int* ptop)    
{
    *ptop=-1;
} 

//空栈判断函数,参数是指向操作符栈顶编号的指针
//如果为空栈返回1,否则返回0 
int isEmpty(int* ptop)     
{
    return *ptop==-1;
} 

//满栈判断函数,参数是指向操作符栈顶编号的指针
//如果为满栈返回1,否则返回0 
int isFull(int* ptop)
{
    return *ptop==MAXSIZE_signStack-1;
}

//报错信息函数 
void Error(char *s)
{
    printf("%s\n",s);
    
    exit(1);
}

//字符栈压栈函数,共有三个参数 
//第一个参数是指向栈数组第一个元素的指针
//第二个参数是要进栈的字符 
//第三个参数是指向操作符栈顶编号的指针 
void push_char(char *s,char item,int* ptop)   
{
    if (isFull(ptop))
    {
        Error("Stack overflow!");
    }
    else
    {
        s[++(*ptop)]=item;
    }
}

//字符栈弹出函数,共有一个参数 
//第一个参数是指向操作符栈顶编号的指针
void pop_char(int* ptop)
{
    if(isEmpty(ptop))
    {
        Error("Stack Empty!");
    }
    else
    {
        --(*ptop);
    }
}

//优先级判断函数,参数是被比较的字符 
int grade(char a)
{
    switch(a)
    {
        case '#':return 0;
        case '(':return 1;
        case '+':
        case '-':return 2;
        case '*':
        case '/':return 3;   
    }
    return -1;
}

三、反波兰表达式的计算方法

1.设定待计算的整数栈;

2.从左到右遍历后缀表达式的每个整数和运算符;

3.若当前字符是数字,则将连续的数字字符用sscanf函数压入真数栈,并且在之后遍历时,跳过这些字符;

4.若当前字符为运算符,则取整数栈最顶上的整数和次顶上的整数进行计算,并将这两者弹出栈,然后将计算结果压入栈中;(注意,若操作符为减号,则应该用次顶上的数字减去最顶上的数字;若操作符为除号,也同样处理)

5.最后栈中只剩下了一个整数,这个整数就是反波兰表达式计算的最终结果。

四、反波兰表达式的计算·示例代码

#include 
#include 

#define MAXSIZE_numStack 100
#define MAXSIZE_expression 1000

int numStack[MAXSIZE_numStack];  //后缀计算数字栈
int numtop;    //后缀计算数字栈栈顶编号

//后缀表达式计算函数及其附属函数的声明
int anti_poland_cal(char* expression); 
void initStack(int* ptop); 
int isEmpty(int* ptop);
int isFull1(int* ptop);
void Error(char *s);
void push_int(int *s,int item,int* ptop);
void pop_int(int* ptop);
 

char expression[MAXSIZE_expression];//待计算后缀表达式
 
 
 
int main(void)
{
    gets(expression);
    
    printf("%d",anti_poland_cal(expression));
    
    return  0;
}

//后缀表达式计算函数
int anti_poland_cal(char* expression)
{
    //设定计算数字栈
    initStack(&numtop);
    
    //遍历中缀表达式
    int i;
    
    int tmp;
    //tmp用于存储读取的数字 
    
    for (i=0;i='0'&&expression[i]<='9')
        {
            sscanf(expression+i,"%d",&tmp);
            
            push_int(numStack,tmp,&numtop);
            
            while (expression[i]>='0'&&expression[i]<='9')
            {
                i++;
            }
            
            i--;
            //因为每一轮for循环都会自动对i进行累加,所以要i-- 
        }
        else if (expression[i]=='+')
        {
            int tmp1,tmp2,result;
            //tmp1和tmp2分别用于存储栈顶和次顶的元素,result用于得出计算结果 
            tmp1=numStack[numtop];
            
            pop_int(&numtop);
            //取值后,直接弹出 
            tmp2=numStack[numtop];
            
            pop_int(&numtop);
            
            result=tmp1+tmp2;
            
            push_int(numStack,result,&numtop);
            //计算结果压入栈 
        }
        else if (expression[i]=='-')
        {
            int tmp1,tmp2,result;
            
            tmp1=numStack[numtop];
            
            pop_int(&numtop);
            
            tmp2=numStack[numtop];
            
            pop_int(&numtop);
            
            result=tmp2-tmp1;
            
            push_int(numStack,result,&numtop);
        }
        else if (expression[i]=='*')
        {
            int tmp1,tmp2,result;
            
            tmp1=numStack[numtop];
            
            pop_int(&numtop);
            
            tmp2=numStack[numtop];
            
            pop_int(&numtop);
            
            result=tmp2*tmp1;
            
            push_int(numStack,result,&numtop);
        }
        else if (expression[i]=='/')
        {
            int tmp1,tmp2,result;
            
            tmp1=numStack[numtop];
            
            pop_int(&numtop);
            
            tmp2=numStack[numtop];
            
            pop_int(&numtop);
            
            result=tmp2/tmp1;
            
            push_int(numStack,result,&numtop);
        }
    }
    
    return numStack[0]; 
    
}

//建栈函数,参数是指向操作符栈顶编号的指针
void initStack(int* ptop)    
{
    *ptop=-1;
} 

//空栈判断函数,参数是指向操作符栈顶编号的指针
//如果为空栈返回1,否则返回0 
int isEmpty(int* ptop)     
{
    return *ptop==-1;
} 

//满栈判断函数,参数是指向操作符栈顶编号的指针
//如果为满栈返回1,否则返回0 
int isFull1(int* ptop)
{
    return *ptop==MAXSIZE_numStack-1;
}

//报错信息函数 
void Error(char *s)
{
    printf("%s\n",s);
    
    exit(1);
}

//整数型压栈函数,共有三个参数 
//第一个参数是指向栈数组第一个元素的指针
//第二个参数是要进栈的整数 
//第三个参数是指向操作符栈顶编号的指针 
void push_int(int *s,int item,int* ptop)   
{
    if (isFull1(ptop))
    {
        Error("Stack overflow!");
    }
    else
    {
        s[++(*ptop)]=item;
    }
}

//整数型栈弹出函数,共有一个参数 
//第一个参数是指向操作符栈顶编号的指针
void pop_int(int* ptop)
{
    if(isEmpty(ptop))
    {
        Error("Stack Empty!");
    }
    else
    {
        --(*ptop);
    }
}

五、特别提醒

请来自航专的同学不要直接复制代码,会查重的!

你可能感兴趣的:(c语言,数据结构,学习)