先看下面的图片,这是后缀表达式32/6*3-3+转前缀的过程
对于表达式:32/6*3-3+
其前缀式为:+-*/32633
操作数的顺序不会改变,变的是运算符的顺序,并且在后缀式中,运算顺序从左往右,在前缀式中,正好反过来(但是运算符不一定正好反过来),这跟我们自己运算这两个表达式的顺序是一样的。转换的关键,就在如何找准操作符的两个操作数。
观察后缀表达式,对于32,越靠右边的操作数对32的运算迫切程度降低,总是要等到前面的运算符运算完才可以对32进行运算,由此想到栈结构来存储运算符。
总的思路如下:
指针从最后边扫描起,遇到操作符则存入栈中并且从表达式中删除该操作符,同时标记其匹配的操作数为0,如果遇到操作数,则应该对栈顶的操作符的配对操作数加一,当新来一个操作符时,对前面操作符的操作数配对期望降低,转而对新来的操作符先行配对操作数。当一个操作符成功配对两个操作数时,其配对期望程度为0,从栈中取出,插入到其两个操作数的前面,整体作为此时栈顶操作符新的操作数,并记录到栈顶操作符的操作数匹配数中。如果此时该栈顶操作符的操作数匹配恰好又为2,则再次取出,插入到其两个操作数前面,迭代此过程,直到栈顶操作符的操作数匹配数不足2或者栈空为止。
因为是如上的考虑,所以表达式存储采用链表,提高插入删除效率。
同时栈的data域要包含两个成员,其一为操作符,其二为该操作符匹配的操作数的数目。
下面是代码:
Status Convert(Expression *exp) {//算法将后缀式exp转换为前缀式,如果后缀式不合法,则返回ERROR SeqStack S; InitStack(&S); Revers(exp);//revers the expression Ptr p = exp; while (p->next!=NULL)//expression is still not over { if (Is_optr(p->next->ch))//is it an operator? { StackElem optr; optr.optr = p->next->ch; optr.its_oprd = 0; Push(&S, optr); Delet(exp, p);//delete the operator from expression } else { if (IsEmpty(&S)) return ERROR;//expression is illegal! else { while (!IsEmpty(&S)) { StackElem optr; GetTop(&S, &optr); Pop(&S); if (++optr.its_oprd < 2) { Push(&S, optr); break; } else { p = p->next; Insert(exp, p, optr.optr); } } p = p->next; } } } if (!IsEmpty(&S)) return ERROR;//expression is illegal! Revers(exp); return OK; }算法包含对后缀正确的判断,错误的后缀式(不算怪异字符,如不应该出现的‘】’‘&’等等)有两种情况,一种是取栈中元素时栈为空,说明此时后缀式存在非法的操作数过多的子表达式,第二种是表达式转换完栈不空,说明后缀式操作符过多。
如果你想运行上面的代码,你需要完整的源代码,如下:
#include "stdafx.h" #include<stdio.h> #include<iostream> #include<malloc.h> #define Status int #define OVERFLOW -1 #define ERROR 0 #define OK 1 #define STACK_INI_SIZE 10//顺序栈初始化长度 #define STACK_INC_SIZE 2//顺序栈单次扩充长度 typedef struct StackElem { char optr; int its_oprd;//属于optr操作数出现的次数 }StackElem;//栈的元素类型 typedef struct SeqStack { StackElem *base; int top; int capacity;//容量 }SeqStack; typedef struct LinkList { char ch;//表达式元素 struct LinkList *next; }Expression,ENode,*Ptr; /*The major function*/ Status Convert(Expression *exp); bool Is_optr(char ch); /*Basic operation of SeqStack*/ //初始化栈 Status InitStack(SeqStack *S); //获取栈顶元素的数据 Status GetTop(SeqStack *S, StackElem *optr); //入栈 Status Push(SeqStack *S, StackElem optr); //出栈 Status Pop(SeqStack *S); //栈判空 bool IsEmpty(SeqStack *S); //扩充栈空间 Status Extern(SeqStack *S); /*Basic operation of Expression*/ //初始化表达式 Status InitExp(Expression **exp); //构建表达式 Status Push_back(Expression *exp, char ch); //插入节点 Status Insert(Expression *exp,Ptr p,char ch); //删除节点 Status Delet(Expression *exp, Ptr p); //逆置表达式 Status Revers(Expression *exp); //输出表达式 Status Show(Expression *exp); int main() { using namespace std; ENode *exp; InitExp(&exp);//初始化空表达式 cout << "Input a postfix expression(press @ to end input),thanks\n"; char ch; while (cin >> ch, ch != '@') { Push_back(exp, ch); }//expression like this 36*32/- if (Convert(exp)) Show(exp); else cout << "Your expression is illegal\n"; return 0; } Status Convert(Expression *exp) {//算法将后缀式exp转换为前缀式,如果后缀式不合法,则返回ERROR SeqStack S; InitStack(&S); Revers(exp);//revers the expression Ptr p = exp; while (p->next!=NULL)//expression is still not over { if (Is_optr(p->next->ch))//is it an operator? { StackElem optr; optr.optr = p->next->ch; optr.its_oprd = 0; Push(&S, optr); Delet(exp, p);//delete the operator from expression } else { if (IsEmpty(&S)) return ERROR;//expression is illegal! else { while (!IsEmpty(&S)) { StackElem optr; GetTop(&S, &optr); Pop(&S); if (++optr.its_oprd < 2) { Push(&S, optr); break; } else { p = p->next; Insert(exp, p, optr.optr); } } p = p->next; } } } if (!IsEmpty(&S)) return ERROR;//expression is illegal! Revers(exp); return OK; } bool Is_optr(char ch) {//判断ch是否是运算符 return ch == '+' || ch == '-' || ch == '*' || ch == '/'; } Status InitStack(SeqStack *S) {//初始化栈 S->base = (StackElem*)malloc(sizeof(StackElem)*STACK_INI_SIZE); if (!S->base) return OVERFLOW; S->capacity = STACK_INI_SIZE; S->top = 0; return OK; } Status GetTop(SeqStack *S, StackElem *optr) {//获取栈顶元素数据 if (IsEmpty(S)) return ERROR; optr->optr = S->base[S->top - 1].optr; optr->its_oprd = S->base[S->top - 1].its_oprd; return OK; } Status Push(SeqStack *S, StackElem optr) { if (S->top == S->capacity && !Extern(S)) return OVERFLOW; S->base[S->top].its_oprd = optr.its_oprd; S->base[S->top].optr = optr.optr; S->top++; return OK; } Status Pop(SeqStack *S) { if (IsEmpty(S)) return ERROR; S->top--; return OK; } bool IsEmpty(SeqStack *S) { return S->top == 0; } Status Extern(SeqStack *S) { StackElem *newbase; newbase = (StackElem*)realloc(S->base, (S->capacity + STACK_INC_SIZE) * sizeof(StackElem)); if (!newbase) return OVERFLOW; S->base = newbase; S->capacity += STACK_INC_SIZE; return OK; } Status InitExp(Expression **exp) {//初始化空表达式 *exp = (ENode*)malloc(sizeof(ENode)); if (!(*exp)) return OVERFLOW; (*exp)->next = NULL; return OK; } Status Push_back(Expression *exp, char ch) {//尾部插入 ENode *p = exp, *s; while (p->next != NULL) { p = p->next; } s = (ENode*)malloc(sizeof(ENode)); if (!s) return OVERFLOW; s->next = NULL; s->ch = ch; s->next = p->next; p->next = s; return OK; } Status Insert(Expression *exp, Ptr p, char ch) {//在指针p的后面插入节点ch ENode *s = (ENode*)malloc(sizeof(ENode)); if (!s) return OVERFLOW; s->next = NULL; s->ch = ch; s->next = p->next; p->next = s; return OK; } Status Delet(Expression *exp, Ptr p) {//删除P后面的节点 if (p->next == NULL) return ERROR; ENode *q = p->next; p->next = q->next; free(q); return OK; } Status Revers(Expression *exp) {//逆置表达式exp if (exp->next == NULL || exp->next->next == NULL) return OK; ENode *p, *s; p = exp->next->next; exp->next->next = NULL; s = p; while (p != NULL) { s = s->next; p->next = exp->next; exp->next = p; p = s; } return OK; } Status Show(Expression *exp) {//输出表达式 ENode *p = exp; while (p->next != NULL) { std::cout << p->next->ch << ' '; p = p->next; } return OK; }
不足之处请提出来,希望能帮到你!