中缀表达式转换成后缀表达式

后缀表达式可以简化计算机对表达式的求值。

中缀表达式:A+B*C,转化为后缀表达式为:ABC*+。计算机求值时,依次读入并压栈,当读到运算符时,去除栈顶的两个元素,运算,并把运算结果入栈。

对于后缀表达式ABC*+的求值过程:

1.读取A, A入栈,栈中元素为A

2. 读取B,B入栈,栈中元素为AB

3. 读取C,C入栈,栈中元素为ABC

4. 读取*,C退栈,B退栈,对B和C执行乘法操作,设t=B*C,t入栈,栈中元素为At

5. 读取+,t退栈,A退栈,对A和t执行加法操作,栈中无元素,表达式的值为A+t,其中t为B*C


再看看有括号的表达式求值,A*(B+C)*D,其后缀表达式为ABC+*D*

对于后缀表达式ABC+*D*的求值过程:

1. 读取A,A入栈,栈中元素为A

2. 读取B,B入栈,栈中元素为AB

3. 读取C,C入栈,栈中元素为ABC

4. 读取+,C退栈,B退栈,执行加法运算,设p=B+C,p入栈,栈中元素为Ap

5. 读取* ,p退栈,A退栈,执行乘法运算,设q=A*p,q入栈,栈中元素为q

6. 读取D,D入栈,栈中元素为qD

7.读取* ,D退栈,q退栈,执行乘法运算,表达式的值为q*D。


可以看出,将中缀表达式转化为后缀表达式,可以去除括号并且产生不具二义性的可用于计算机计算的表达式。那么,关键是如用程序将中缀表达式转化为后缀表达式。

思路:

1.后缀表达式与中缀表达式中的操作数的顺序不变,只是去除了括号和改变了操作符的位置。

2.需要借助一个栈,来操作运算符。

用代码来说明:

myStack.h

#pragma once
#include <memory.h>
template<class T>
class myStack
{
public:
	myStack(int capacity=10);
	~myStack(void);
	void push(T e);
	T pop();
	bool isEmpty();
	T copyTop();

private:
	T* array;
	int capacity;
	int top;
	
	void addSize();
};

template<class T>
myStack<T>::myStack(int capacity/*=10*/)
{
	array =new T[capacity];
	//top=-1  说明为空
	top=-1;
	this->capacity=capacity;
}
template<class T>
void myStack<T>::push(T e)
{
	if(top+1==capacity)
		addSize();
	array[++top]=e;
}
template<class T>
T  myStack<T>::pop()
{
	return array[top--];
}
template<class T>
myStack<T>::~myStack(void)
{
	delete[] array;
}
template<class T>
void myStack<T>::addSize()
{
	T* temp=new T[capacity+10];
	memcpy(temp,array,sizeof(T)*(capacity+10));
	delete[] array;
	array=temp;
	capacity+=10;
}
template<class T>
bool myStack<T>::isEmpty()
{
	return top==-1;
}
template<class T>
T myStack<T>::copyTop()
{
	return array[top];
}
infix2postfix.h

#pragma once
#include "myStack.h"
class infix2postfix
{
public:
	infix2postfix(char *str);
	~infix2postfix(void);
	//打印后缀表达式
	void printPostfix();

private:
	//符号进栈,出栈操作
	myStack<char> s;
	char *src;
	char *result;
	int index;
	//获取除去了之后的字符串长度,用以申请result空间
	int getValidLength();
	//获取后缀表达式
	void getPostfix();
	//处理括号
	void processBrackets(char c);
	//处理运算符
	void processOperator(char c);
	//处理操作数
	void processOperand(char c);
};
infix2postfix.cpp

#include "infix2postfix.h"
#include <string.h>
#include <iostream>
using namespace std;
infix2postfix::infix2postfix(char*str)
{
	index=0;
	src=new char[strlen(str)+1];
	strcpy(src,str);
	result=new char[getValidLength()+1];
	result[getValidLength()]=0;
	getPostfix();
}

infix2postfix::~infix2postfix(void)
{
	delete[]src;
	delete[]result;
}
//获取除去了之后的字符串长度,用以申请result空间
int infix2postfix::getValidLength()
{
	char *p=src;
	int len=0;
	while(*p++!=0)
	{
		if(*p!='(' && *p!=')')
			len++;
	}
	return len;
}
//打印后缀表达式
void infix2postfix::printPostfix()
{
	cout<<"中缀:"<<src<<endl;
	cout<<"后缀:"<<result<<endl<<endl;
}
//获取后缀表达式
void infix2postfix::getPostfix()
{
	char*p=src;
	while(*p!=0)
	{
		if(*p=='(' || *p==')')
			processBrackets(*p);
		else if(*p=='+' || *p=='-' || *p=='*' || *p=='/')
			processOperator(*p);
		else
			processOperand(*p);
		p++;
	}
	while(!s.isEmpty())
		result[index++]=s.pop();
}
//处理括号
void infix2postfix::processBrackets(char c)
{
	if(c=='(')
		s.push(c);
	else
	{
		char e;
		while( (e=s.pop())!='(' )
			result[index++]=e;
	}
}
/*
**处理运算符
**如果是'+'或'-',把运算符栈s依次退栈,直到遇见'(',并存入后缀表达式
**如果是'*'或'/',把运算符栈s依次退栈,直到遇见'(','+','-',并存入后缀表达式
*/
void infix2postfix::processOperator(char c)
{
	bool flag=false;
	if(c=='+' || c=='-')
		flag=true;
	while(!s.isEmpty())
	{
		if(s.copyTop()!='(' && (flag|| (s.copyTop()!='+' && s.copyTop()!='-') ))
			result[index++]=s.pop();
		else
			break;
	}
	s.push(c);
}
//处理操作数,直接存入后缀表达式
void infix2postfix::processOperand(char c)
{
	result[index++]=c;
}

main.cpp

#include <iostream>
#include "infix2postfix.h"

int main()
{
	infix2postfix i2p("A*B+c");
	i2p.printPostfix();

	infix2postfix i2p2("A/B-C+D*E-A*C");
	i2p2.printPostfix();

	infix2postfix i2p3("a*(b+c)*d");
	i2p3.printPostfix();
}

中缀表达式转换成后缀表达式_第1张图片





你可能感兴趣的:(中缀表达式转换成后缀表达式)