中缀表达式(Infix Notation)的求解,只考虑双目运算符情况

最近看了数据结构的书,刚刚学到栈,其中的一大应用就是求中缀表达式的值,于是实现了一个。(书上的代码错误好多)

 

先要说明一下:
1、什么是栈结构
2、什么是中缀表达式

 

栈(stack,也叫堆栈)
Wikipedia:http://en.wikipedia.org/wiki/Stack_(abstract_data_type)

 

栈是一种抽象数据结构(ADT, Abstract Data Type),可以比喻为只有一个出口的仓库,属于 Last-In-First-Out 结构,先进入的元素保存在栈底,后进入的元素依次从栈底向栈顶放置;当一个栈非空的时候,只能依次从栈顶取出元素。所以栈结构是先入后出的。

栈的操作主要有两种:入栈(Push,也有叫 压入,进栈等的),出栈(Pop,也有叫 弹出的)。
如果一个栈使用链式结构,那么整个栈的容量只取决于内存允许的容量。

 

中缀表达式(InfixNotation)
Wikipedia:http://en.wikipedia.org/wiki/Infix_notation

 

这是最常见的表达式,表达式就是用运算符连接起来有运算意义的式子,比如:
1+5*(2+1)

 

常见运算符(operator)有 + - * / % ^ ( )
而参与运算的叫做操作数(oprand),比如例子中的 1 5 2 1


由于运算符有优先级,所以一个表达式的求值需要考虑那两个运算符先运算,那两个后运算的问题。

但是如果从左向右读取表达式,然后根据运算符的先后顺序,再利用栈就可以求得一个表达式的值。

 

中缀表达式的运算规则如下:
·根据运算符优先级由高到低的顺序进行运算
·有括号出现时先算括号内的,后算括号外的,多层括号,由内向外进行
·乘方连续出现时先算最右面的

 

运算符之间存在如下比较关系
 * The operators' priority is show below:
(Comparison direction: Opt2 to Opt1)

运算符比较
  opt2              
op1 ^ * / + - ( ) #
^ > > > > > < > >
* < > > > > < > >
/ < > > > > < > >
+ < < < > > < > >
- < < < > > < > >
( < < < < < < =  
) > > > > >   > >
# < < < < < <   =

 

注意这些比较符左边为 opt1 右边为 opt2。

 

中缀表达式求值需要两个栈,操作数栈 s1,和运算符栈 s2

 

实现过程为:
1.置操作数栈 s1 为空栈,运算符栈 s2 中预设一个最低级的运算符 '#'


2.依次从左向右读入表达式的每一个字符


3.如果当前字符是操作数,入操作数栈 s1


4.如果当前字符是运算符,则:
 1)若这个运算符 θ2 比栈顶运算符 θ1 优先级高,则入运算符栈 s2,转到 2
 2)若这个运算符 θ2 比栈顶运算符 θ1 优先级低,则从操作数栈 s1 弹出两个操作数,从运算符栈 s2 弹出一个运算符进行运算,并将其结果压入操作数栈 s1,并转到 3
 3)若这个运算符 θ2 与栈顶运算符 θ1 的优先级相同,从操作符栈 s2 弹出栈顶元素,并转到 2


5.直到遇到结束符 '#'

 

以下是运行结果:

 

附上代码:

堆栈(模板)

template 
class StackNode{
	public:
		T value;
		StackNode *next;

		StackNode(T d=0){value=d;next=NULL;}
};

template 
class LinkStack{
		StackNode *top;

	public:
		LinkStack(){top=new StackNode();top->next=NULL;}
		~LinkStack();
		void Push(T value);//Push value into stack
		T Pop();//Pop value out of stack
		T GetTop();//Get the top node's value without pop it
		bool IsEmpty();//whether the stack is empty
		void Clear();//Clear the stack;
};

template 
LinkStack::~LinkStack()
{
	StackNode *p=NULL;

	while (!IsEmpty()){
		p=top->next;
		top->next=p->next;
		delete p;
	}

	delete top;
}

template 
void LinkStack::Push(T value)
{
	StackNode *p=NULL;
	p=new StackNode(value);
	p->next=top->next;
	top->next=p;
//cout<<"Push: "<
T LinkStack::Pop()
{
	if (top->next!=NULL){
		StackNode *p=top->next;
		T retvalue=p->value;
		top->next=p->next;
		delete p;
//cout<<"Pop: "<
T LinkStack::GetTop()
{
	if (top->next!=NULL){
		return (top->next->value);
	}else{
		cerr<<"The stack is empty."<
bool LinkStack::IsEmpty()
{
	return (top->next==NULL);
}

template 
void LinkStack::Clear()
{
	StackNode *p=NULL;

	while (!IsEmpty()){
		p=top->next;
		top->next=p->next;
		delete p;
	}
}


double eval() 函数代码

double eval()
{
	double number=0.0;//store the number in string
	char c;

	LinkStack OprandStack;
	LinkStack OperatorStack;
	OperatorStack.Push('#');

	while (!OperatorStack.IsEmpty()){//read the expression
		//expression evaluate
		if (cin.peek()>='0' && cin.peek()<='9'){//current char is oprand

			cin>>number;
			cout<' case
			double a,b;
			char opt;

			b=OprandStack.Pop();
			a=OprandStack.Pop();
			opt=OperatorStack.Pop();

			OprandStack.Push(Operate(a,opt,b));
		}
	}

	return (OprandStack.GetTop());
}


支撑函数代码:

//returns true when c is in the set:
//^ * / + - ( ) #
bool IsOperator(char c)
{
	return (c=='^' || c=='*' || c=='/' || c=='+' ||
		c=='-' || c=='(' || c==')' || c=='#');
}

char CompareOpt(char opt1,char opt2)
{
	//priority table
	//row 0 is the operator
	//row 1-8 is the relationship

	char priority[9][9]={
		{' ','^','*','/','+','-','(',')','#'},
		{'^','>','>','>','>','>','<','>','>'},
		{'*','<','>','>','>','>','<','>','>'},
		{'/','<','>','>','>','>','<','>','>'},
		{'+','<','<','<','>','>','<','>','>'},
		{'-','<','<','<','>','>','<','>','>'},
		{'(','<','<','<','<','<','<','=',' '},
		{')','>','>','>','>','>',' ','>','>'},
		{'#','<','<','<','<','<','<',' ','='}
	};

	int row=0,col=0;

	for (int i=0;i<9;i++){
		if (opt2==priority[0][i]) col=i;
		if (opt1==priority[i][0]) row=i;
	}

	return priority[row][col];
}

double Operate(double a,char opt,double b)
{
	double result=0.0;
	int i=0;

	switch (opt){
		case '^':
			i=int(b);
			result=1;
			while (i--){result*=a;}
			break;
		case '*':
			result=a*b;
			break;
		case '/':
			result=a/b;
			break;
		case '+':
			result=a+b;
			break;
		case '-':
			result=a-b;
			break;
		default:
			result=a;
			break;
	}

	return result;
}


 

主函数代码:

#include "InfixExpression.h"

int main()
{
	double result=0.0;

	while(1){
		cout<<"Input expression:('@' for exit)"<

你可能感兴趣的:(C++,Algorithm,class,数据结构,null,c,stream,delete)