根据后缀表达式输出数学表达式,也就是说将先运算的项加括号,但是多余的括号省略(比如本来就是先运算的项、适用结合律)。
算法默认输入的表达式是正确的,所以没有检错能力、也不支持超过一位的操作数、操作符只有加减乘除
算法的大体思路是先由后缀表达式构建二叉树,用一个栈依次存放字符,遇到运算操作数就直接入栈,遇到运算符就弾出两个元素,分别作为运算符的右子树和左子树(注意顺序不能错,因为减法和除法是左子树的数作用右子树的数),然后把这颗子树入栈。做到最后栈里只剩一个根结点,整棵树就构建成功了。
然后通过中序遍历访问树的每一个分支结点,看是哪种运算符,再看左子树或右子树是哪种运算符,根据不同的情况使用对应的输出方法。通过分析我们找到哪种情况下括号是不能省略的:'+'对右边的'-'运算不能省略,'-'对右边的'+'和'-'运算,'*'对左边的'+'和'-'运算、对右边的'/''+''-'运算,'/'对左边的'+'和'-'以及对右边的所有运算不能省略。
#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;
}