栈实现后缀表达式转前缀表达式

先看下面的图片,这是后缀表达式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;
}

不足之处请提出来,希望能帮到你!

猜你喜欢

转载自blog.csdn.net/weixin_41133154/article/details/79056971