根据逆波兰式输出带括号的数学表达式

根据后缀表达式输出数学表达式,也就是说将先运算的项加括号,但是多余的括号省略(比如本来就是先运算的项、适用结合律)。

算法默认输入的表达式是正确的,所以没有检错能力、也不支持超过一位的操作数、操作符只有加减乘除

算法的大体思路是先由后缀表达式构建二叉树,用一个栈依次存放字符,遇到运算操作数就直接入栈,遇到运算符就弾出两个元素,分别作为运算符的右子树和左子树(注意顺序不能错,因为减法和除法是左子树的数作用右子树的数),然后把这颗子树入栈。做到最后栈里只剩一个根结点,整棵树就构建成功了。
然后通过中序遍历访问树的每一个分支结点,看是哪种运算符,再看左子树或右子树是哪种运算符,根据不同的情况使用对应的输出方法。通过分析我们找到哪种情况下括号是不能省略的:'+'对右边的'-'运算不能省略,'-'对右边的'+'和'-'运算,'*'对左边的'+'和'-'运算、对右边的'/''+''-'运算,'/'对左边的'+'和'-'以及对右边的所有运算不能省略。

#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 30
typedef char TreeElem;
typedef struct BTree{
    TreeElem elem;
    BTree* lchild;
    BTree* rchild;
}BiTree;

typedef BiTree* StackElem;
typedef struct SqStack{
    StackElem data[MAXSIZE];
    int top;
}Stack;


//判断操作符和操作数
bool isOperator(TreeElem elem){
    return elem == '+' || elem == '-' || elem == '*' || elem == '/';
}

bool isOperand(TreeElem elem){
    return (elem >= 'a' && elem <= 'z') || 
        (elem >= '0' && elem <= '9');
}


//用生成好的二叉树输出表达式
void showExpr(BiTree* t){
    if(t != NULL){
        if(isOperand(t->elem)){
            printf("%c",t->elem);
            return;
        }
        
        TreeElem le = '\0', re = '\0';
        if(t->lchild != NULL) le = t->lchild->elem;
        if(t->rchild != NULL) re = t->rchild->elem;

        if(t->elem == '+'){
            showExpr(t->lchild);
            printf("+");
            if(re == '-'){
                printf("(");
                showExpr(t->rchild);
                printf(")");
            }
            else showExpr(t->rchild);
        }
    
        else if(t->elem == '-'){
            showExpr(t->lchild);
            printf("-");
            if(re == '+' || re == '-'){
                printf("(");
                showExpr(t->rchild);
                printf(")");              
            }
            else showExpr(t->rchild);
        }

        else if(t->elem == '*'){
            if(le == '+' || le == '-'){
                printf("(");
                showExpr(t->lchild);
                printf(")");
            }
            else showExpr(t->lchild);

            printf("*");

            if(re == '/' || re == '+' || re == '-'){
                printf("(");
                showExpr(t->rchild);
                printf(")");
            }
            else showExpr(t->rchild);
        }

        else if(t->elem == '/'){
            if(le == '+' || le == '-'){
                printf("(");
                showExpr(t->lchild);
                printf(")");
            }
            else showExpr(t->lchild);

            printf("/");

            if(isOperator(re)){
                printf("(");
                showExpr(t->rchild);
                printf(")");
            }
            else showExpr(t->rchild);
        }
    }
}


//由后缀表达式构建二叉树
BiTree* post2tree(char li[],int len){
    Stack* stack = NULL;
    initStack(stack);
    BiTree* tree = NULL;
    
    for(int i = 0;i < len;i++){
        if(isOperand(li[i])){
            tree = (BiTree*)malloc(sizeof(BiTree));
            tree->elem = li[i];
            tree->lchild = tree->rchild = NULL;
            push(stack, tree);
        }
        else if(isOperator(li[i]) && !empty(stack)){
            tree = (BiTree*)malloc(sizeof(BiTree));
            tree->elem = li[i];
            tree->rchild = pop(stack);
            tree->lchild = pop(stack);
            push(stack, tree);
        }
    }
    BiTree* b = pop(stack);
    delStack(stack);
    return b;
}


BiTree* post2tree(){
    Stack* stack = NULL;
    initStack(stack);
    BiTree* tree = NULL;
    char ch;
    printf("input post-expression:");
    scanf("%c",&ch);
    
    while(ch != '\n'){
        if(isOperand(ch)){
            tree = (BiTree*)malloc(sizeof(BiTree));
            tree->elem = ch;
            tree->lchild = tree->rchild = NULL;
            push(stack, tree);
        }
        else if(isOperator(ch) && !empty(stack)){
            tree = (BiTree*)malloc(sizeof(BiTree));
            tree->elem = ch;
            tree->rchild = pop(stack);
            tree->lchild = pop(stack);
            push(stack, tree);
        }
        scanf("%c",&ch);
    }
    BiTree* b = pop(stack);
    delStack(stack);
    return b;
}


void initStack(Stack *&s){
    s = (Stack*)malloc(sizeof(Stack));
    s->top = -1;
}


void delStack(Stack *&s){
    free(s);
}


bool empty(Stack *s){
    return s->top == -1;
}


bool push(Stack *&s,StackElem e){
    if(s->top >= MAXSIZE-1 || s->top < -1){
        printf("Push Error!");
        return false;
    }
    s->top++;
    s->data[s->top] = e;
    return true;
}


StackElem pop(Stack *&s){
    if(s->top > -1){
        StackElem e = s->data[s->top];
        s->top--;
        return e;
    }
    else{
        printf("Pop Error:s->top <= -1");
        exit(1);
    }
}

测试

int main(){
    char li1[] = "ab+cd*ef++-ghi/-+";
    char li2[] = "ab*cd+*efgh/*//";
    BiTree* t = post2tree(li1,17);
    showExpr(t);
    printf("\n");
    
    t = post2tree(li2,15);
    showExpr(t);
    printf("\n");

    system("pause");
    return 0;
}

根据逆波兰式输出带括号的数学表达式

上一篇:单链表c++实现


下一篇:C++解析XML文件(一、 CMarkUp的使用)