noj21逆波兰表达式

在这里插入图片描述
回顾一下逆波兰式:

逆波兰表达式又叫做后缀表达式。逆波兰表示法是波兰逻辑学家J・卢卡西维兹于1929年首先提出的一种表达式的表示方法。后来,人们就把用这种表示法写出的表达式称作“逆波兰表达式”。逆波兰表达式把运算量写在前面,把算符写在后面。
重点:

  1. 符号栈中,栈顶优先级最高
  2. 向符号栈中加入符号时,要对比栈顶符号的优先级是否小于当前符号的优先级,如果小于则直接入栈,如果大于则要将栈内元素弹出,一直弹出至当前的栈顶符号的优先级小于当前符号,然后再将当前符号入栈
  3. 如果入栈符号为 ( ,则直接入栈
  4. 如果入栈符号为 ) ,则要循环弹栈,一直到栈顶元素为 ( ,为止,最后还要将栈顶元素 ( 弹出

优先级:
±优先级小于 * /,且 + 和 - 的优先级相同, * 和 / 的优先级相同

原文链接:https://blog.csdn.net/assiduous_me/article/details/101981332

如果当前元素是数字,那么就直接压入栈
如果当前元素是运算符,那么一次性弹出两个元素,同时后弹出来的作为加数或者被减数或者乘数或者被除数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max 100

typedef enum{character,operate}flag;
//括号字母,操作符加减乘除

typedef struct Node
{
    char elem;//字符
    int rank;//优先级
    flag tag;//标志
}Node;

typedef struct BiNode
{
    Node data;//元素
    struct BiNode *left,*right;
}BiNode,*BiTree;

typedef struct NewString
{
    Node data[max];
    int length;//长度
}NewString;

//初始化字符串
NewString InitString()
{
    char str[max];
    NewString S;
    int len=0,level=0;//长度,基本优先级
    scanf("%s",str);
    len = strlen(str);
    S.length=len;
    for(int i=0;i<S.length;i++)
    {
        S.data[i].elem=str[i];//赋值
        //分辨等级
        if(str[i]=='+'||str[i]=='-')
        {
            S.data[i].rank=level+1;
            S.data[i].tag=operate;
            //加减优先级+1
        }
        else if(str[i]=='*'||str[i]=='/')
        {
            S.data[i].rank=level+2;
            S.data[i].tag=operate;
            //乘除优先级+2
        }
        else if(str[i]=='(')
        {
            S.data[i].rank=level+2;
            level += 2;
        }
        else if(str[i]==')')
        {
            S.data[i].rank=level-2;
            level -= 2;
        }
        else
        {
            //字母不计优先级
            S.data[i].tag=character;
        }
    }
    return S;
}
//去掉括号
void ClearBrackets(NewString* S)
{
    int level=0;
    if(S->data[0].elem=='('&&S->data[S->length-1].elem==')')
    {
        for(int i=0;i<S->length-2;i++)
        {
            if(S->data[0].elem=='(')
            {
                level++;
            }
            else if(S->data[0].elem==')')
            {
                level--;
            }
            if(level==0)
            {
                return;
            }
        }
        for(int i=0;i<S->length-2;i++)
        {
            S->data[i]=S->data[i+1];//向前挪一位,把第一位(与最后一位)去掉
        }
        S->length=S->length-2;//长度-2
    }
}
//找到最低优先级位置
int FindMin(NewString *S)
{
    int pos=0,min=1000;
    for(int i=0;i<S->length;i++)
    {
        if(S->data[i].tag==operate && S->data[i].rank<=min)
        {
            min=S->data[i].rank;
            pos=i;
        }
    }
    return pos;
}
//创建二叉树
BiTree CreateBiTree(NewString *S)
{
    BiTree T;
    T=(BiTree)malloc(sizeof(BiNode));

    NewString *left,*right;
    left=(NewString*)malloc(sizeof(NewString));
    right=(NewString*)malloc(sizeof(NewString));
    int midpos,len;
    len=S->length;
    if(len==1)
    {
        T->data=S->data[0];
        T->left=NULL;
        T->right=NULL;
    }
    else
    {
        midpos=FindMin(S);
        left->length=midpos;
        for(int i=0;i<left->length;i++)
        {
            left->data[i]=S->data[i];
        }
        right->length=S->length-midpos-1;
        for(int i=0;i<right->length;i++)
        {
            right->data[i]=S->data[midpos+i+1];
        }
        ClearBrackets(left);//清理一下括号
        ClearBrackets(right);
        T->data=S->data[midpos];
        T->left=CreateBiTree(left);
        T->right=CreateBiTree(right);
    }
    return T;
}
//后序遍历
void LRDPrint(BiTree T)
{
    if(T==NULL)
    {
        return;
    }
    else
    {
        LRDPrint(T->left);
        LRDPrint(T->right);
        printf("%c",T->data.elem);
    }
}
int main()
{
    NewString S;
    S=InitString();
    BiTree T;
    T=CreateBiTree(&S);
    LRDPrint(T);
    return 0;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值