假如给定一个中缀表达式:1+(2-3)*4+10/5利用栈就可以导出后缀表达式123-4*+105/+
导出时注意:操作符入栈,操作数不入栈,在符号“+-*/()”入栈时如果栈中的出现了括号匹配时,需要匹配括号中的符号弹出。如果操作符入栈栈中有级别高或者相等的,就需要将栈中这样级别高或者想到的先出栈,格式肯定是操作数在前,操作符在后的。具体看这个视频:http://v.youku.com/v_show/id_XNTg3MDc0ODQw.html
当得到一个后缀表达式时就很容易的求出表达式的值了,也是用栈计算的,对于123-4*+105/+,从前往后,如果遇到操作数的时候直接入栈,遇到操作符,就从栈中弹出两个操作,那下面的跟上面的那个预算,就可以得到123-4*+105/+的值为-1了,张铭的数据结构堆栈中讲的有。
下面是个中缀表达式的例子:
Stack.h
#include <stdio.h>
#include <malloc.h>
//栈节点数据结构
class DoubleNode
{
friend class DoubleStack;
private:
double value;
DoubleNode *next;
//构造函数
DoubleNode(double value, DoubleNode *p):value(value),next(p){}
};
//栈,用来保存采用后缀表达式进行四则运算时的操作数
class DoubleStack
{
private:
DoubleNode *top;
public:
DoubleStack():top(NULL){}
~DoubleStack();
void push(double value);
double pop();
bool isEmpty(){return top == NULL;}
double getTop();
};
//栈节点数据结构
class CharNode
{
friend class CharStack;
private:
char value;
CharNode *next;
//构造函数
CharNode(char value, CharNode *p):value(value),next(p){}
};
//栈,用来保存中缀表达式转换成后缀表达式时的运算符
class CharStack
{
private:
CharNode *top;
public:
CharStack():top(NULL){}
~CharStack();
void push(char value);
char pop();
bool isEmpty(){return top == NULL;}
char getTop();
void makeEmpty();
};
Stack.cpp
#include "Stack.h"
DoubleStack::~DoubleStack()
{
DoubleNode *p;
while (NULL != top)
{
p = top;
top = top->next;
delete p;
}
}
void DoubleStack::push(double value)
{
top = new DoubleNode(value,top);
}
double DoubleStack::pop()
{
if (!isEmpty())
{
DoubleNode *p;
p = top;
top = top->next;
double nodeValue = p->value;
delete p;
return nodeValue;
}
}
double DoubleStack::getTop()
{
return top->value;
}
CharStack::~CharStack()
{
CharNode *p;
while (NULL != top)
{
p = top;
top = top->next;
delete p;
}
}
void CharStack::push(char value)
{
top = new CharNode(value,top);
}
char CharStack::pop()
{
if (!isEmpty())
{
CharNode *p;
p = top;
top = top->next;
char nodeValue = p->value;
delete p;
return nodeValue;
}
}
void CharStack::makeEmpty()
{
CharNode *p;
while (NULL != top)
{
p = top;
top = top->next;
delete p;
}
}
char CharStack::getTop()
{
return top->value;
}
arithmetic.h
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include "Stack.h"
class Data
{
public:
double num;
char op;
};
class Arithmetic
{
private:
DoubleStack dStack; //保存四则运算时,后缀表达式中的操作数
CharStack cStack; //保存中缀表达式转换成后缀表达式过程中的操作符
int isp(char op); //栈内优先级
int icp(char op); //栈外优先级
public:
Data post[100]; //保存后缀表达式
int curLen; //后缀表达式数组的实际长度
void midTopost(char *c); //把中缀表达式转换成后缀表达式
double calculate(); //进行四则运算
};
arithmetic.cpp
#include "arithmetic.h"
void Arithmetic::midTopost(char *c)
{
int i = 0;
int k;
int j;
char tmp;
char a[100];
char num[10];
//下面开始把字符串中的操作符(+-*/)放入后缀表达式
cStack.makeEmpty();
cStack.push('#');
//字符串最后都加一个#
strcat(c, "#");
k = 0;
while (c[k] != '\0')
{
if (c[k] == '+' || c[k] == '-' || c[k] == '*' || c[k] == '/' || c[k] == '(')
{
//如果优先级低,一直退栈,否则入栈
while (isp(cStack.getTop()) > icp(c[k]))
{
post[i++].op = cStack.pop();
}
cStack.push(c[k]);
}
else if (c[k] == ')')
{
//一直退栈到'('
while (isp(cStack.getTop()) >= icp(')'))
{
tmp = cStack.pop();
if (tmp != '(')
{
post[i++].op = tmp;
}
}
}
else if (c[k] == '#')
{
while (isp(cStack.getTop()) > icp('#'))
{
tmp = cStack.pop();
post[i++].op = tmp;
}
}
else if (c[k] >= '0' && c[k] <= '9')
{
//数字,继续往后获取字符,如果是数字,全部拼装到num中,然后转换成double类型
j = 0;
memset(num, 0, 10);
num[j] = c[k];
k = k + 1;
while (c[k] >= '0' && c[k] <= '9')
{
num[++j] = c[k];
k++;
}
post[i].num = atof(num);
post[i].op = '#';
i++;
k--;
}
else
{
//其他非法字符,不处理
}
k++;
}
curLen = i;
}
//栈内优先级,栈内优先级大于栈外优先级
//'('的栈内优先级应该比所有的操作符都小(除了#)
//')'的栈内优先级应该最大
//+-的优先级一致,*/的优先级一致
int Arithmetic::isp(char op)
{
int pri;
switch (op)
{
case '#' : pri = 0;
break;
case '(' : pri = 1;
break;
case '+' : pri = 3;
break;
case '-' : pri = 3;
break;
case '*' : pri = 5;
break;
case '/' : pri = 5;
break;
case ')' : pri = 10;
break;
}
return pri;
}
//栈外优先级
int Arithmetic::icp(char op)
{
int pri;
switch (op)
{
case '#' : pri = 0;
break;
case '(' : pri = 10;
break;
case '+' : pri = 2;
break;
case '-' : pri = 2;
break;
case '*' : pri = 4;
break;
case '/' : pri = 4;
break;
case ')' : pri = 1;
break;
}
return pri;
}
//根据后缀表达式进行四则运算
double Arithmetic::calculate()
{
int i;
double result = 0;
double left, right;
for (i = 0; i < curLen; i++)
{
//如果是数字就入栈
if (post[i].op == '#')
{
dStack.push(post[i].num);
}
else //如果是操作符,就取出两个数字进行运算
{
right = dStack.pop();
left = dStack.pop();
switch (post[i].op)
{
case '+' : dStack.push(left + right);
break;
case '-' : dStack.push(left - right);
break;
case '*' : dStack.push(left * right);
break;
case '/' : dStack.push(left / right);
break;
}
}
}
return dStack.pop();
}
main.cpp
#include "arithmetic.h"
int main()
{
char tmp[100];
printf("please input a arithmetic express:\n");
scanf("%s", tmp);
Arithmetic ari = Arithmetic();
ari.midTopost(tmp);
printf("the result = [%f]/n", ari.calculate());
system("pause") ;
}