noj 21、采用有向无环图输出逆波兰表达式

在这里插入图片描述
记一下遇到的问题:
1、判断外层括号是否匹配
2、相同优先级,从左到右计算

// 思路:题目要求有向无环图,这里采用二叉树,理论上二叉树是特殊的有向无环图(DAG)
// 给符号添加优先级,以优先级最小的符号划分左右字符,递归建立二叉树。
// 关键问题再括号匹配判断中,设level=0;遇到’(’,level+1;遇到’)’,level-1;如果再达到最后一个‘)’前,level==0,则第一个‘(’
// 不和最后一个‘)’匹配,则不用去除外层括号。

// 思路:题目要求有向无环图,这里采用二叉树,理论上二叉树是特殊的有向无环图(DAG)
// 给符号添加优先级,以优先级最小的符号划分左右字符,递归建立二叉树。
// 关键问题再括号匹配判断中,设level=0;遇到'(',level+1;遇到')',level-1;如果再达到最后一个‘)’前,level==0,则第一个‘(’
// 不和最后一个‘)’匹配,则不用去除外层括号。

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

#define max 2000
typedef struct Snode{
    int tag;   //标签
    char elem;
    int prio;  //优先级
} Snode; //字符节点

typedef struct MyString{
    Snode data[max];
    int length;
}MyString;  //存储字符串

typedef struct TNode{
    Snode data;
    struct TNode *lchild,*rchild;
}TNode,BiTree,*PTNode;   //二叉树

void Clear(MyString *S)//去除外层多余的括号
{
    int level = 0;
    if(S->data[0].elem == '(' && S->data[S->length - 1].elem == ')'){
        for(int i = 0;i < S->length-1;i++)
        {
            if(S->data[i].elem == '(')
            level++;
            else if(S->data[i].elem == ')')
            level--;

            if(level == 0)
            return;
        }

        for(int i = 1; i < S->length-1;i++)
        {
            S->data[i-1] = S->data[i];
        }
        S->length = S->length - 2;
    }
}

void InitString(MyString *S){
    char c[max];
    int len,baselevel = 0;

    scanf("%s",c);
    len = strlen(c);
    for(int i = 0;i < len;i++)
    {
        S->data[i].elem = c[i];
		if (c[i] == '+' || c[i] == '-')
		{
			S->data[i].tag = 1;
			S->data[i].prio = baselevel + 1;
		}
		else if (c[i] == '*' || c[i] == '/')
		{
			S->data[i].tag = 1;
			S->data[i].prio = baselevel + 2;
		}
		else if (c[i] == '(')
		{
			S->data[i].tag = 0;
			baselevel = baselevel + 2;
		}
		else if (c[i] == ')')
		{
			S->data[i].tag = 0;
			baselevel = baselevel - 2;
		}
		else
		{
			S->data[i].tag = 0;
		}
    }
    S->length = len;
}

int FindMid(MyString *S){ //返回level最小符号的下标
    int pos = 0,min = max;//min 当前最小的level,pos记录下标
    for(int i = 0;i < S->length;i++)
    {
        if(S->data[i].prio <= min && S->data[i].tag == 1)// 优先级相同时,先算前面的,所以将后面的作为中间值划分。
        {
            min = S->data[i].prio;
            pos = i;
        }
    }
    return pos;
}

PTNode CreatTree(MyString *S){
    MyString left,right;
    PTNode T;
    T = (PTNode)malloc(sizeof(TNode));
    int midpos,len;
    len = S->length;
    
    if(len == 1)
    {
        T->data = S->data[len-1];
        T->lchild = NULL;
        T->rchild = NULL;
    }
    else if(len > 1)
    {
        midpos = FindMid(S);
        left.length = midpos;
        for(int i = 0;i < midpos;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[i+midpos+1];
        }
        Clear(&left);
        Clear(&right);
        T->data = S->data[midpos];
        T->lchild = (TNode*)malloc(sizeof(TNode));
        T->rchild = (TNode*)malloc(sizeof(TNode));

        T->lchild = CreatTree(&left);
        T->rchild = CreatTree(&right);
    }
    return T;
}

void Last(BiTree* T){
    if(T->lchild == NULL && T->rchild == NULL)
    {
        printf("%c",T->data.elem);
    }
    else
    {
        Last(T->lchild);
        Last(T->rchild);
        printf("%c",T->data.elem);
    }
    
}

int main(){
    MyString s;
    s.length = 0;
    PTNode T;

    InitString(&s);
    Clear(&s);
    T = CreatTree(&s);
    Last(T);
    printf("\n");

    return 0;
}
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

染阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值