最近看了数据结构的书,刚刚学到栈,其中的一大应用就是求中缀表达式的值,于是实现了一个。(书上的代码错误好多)
先要说明一下:
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)"<