您的位置:首页 > 其它

栈的应用---求表达的值

2015-11-30 12:57 197 查看
一、题目

求一个表达式的值,比如9+(3-1)*3+10/2

二、思路

S1.把中缀表达式转换为后缀表达式

S2.根据后比对表达式得到计算结果

三、中缀表达式、后缀表达式

中缀表达式(或中缀记法)是一个通用的算术或逻辑公式表示方法, 操作符是以中缀形式处于操作数的中间(例:9+(3-1)*3+10/2
),中缀表达式是人们常用的算术表示方法。不容易被计算机解析。

后缀表达式:不包含括号,运算符放在两个运算对象的后面,所有的计算按运算符出现的顺序,严格从左向右进行(不再考虑运算符的优先规则,如:(2
+ 1) * 3 , 即2 1 + 3 *

四、中缀转后缀(逆波兰算法)

规则:从左到右遍历中缀表达式的每个数字和符号,若是数字就输出,即成为后缀表达式的一部分;若是符号,则判断其与栈顶符号的优先级,是右括号或优先级低于找顶符号(乘除优先加减)则栈顶元素依次出找并输出,并将当前符号进栈,一直到最终输出后缀表达式为止。

1.遇到操作数:直接输出(添加到后缀表达式中)

2.栈为空时,遇到运算符,直接入栈

3.遇到左括号:将其入栈

4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。

5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算

符入栈

6.最终将栈中的元素依次出栈,输出。

下面我们来具体看看这个过程。

1. 初始化一空栈,用来对符号进出栈使用。

2. 第一个字符是数字9,输出9,后面是符号“+”,进



3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。

4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。



5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,我们需要去匹配此前的“(”,所以栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,因此输出“-”,总的输出表达式为9 3 1 -

6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,因为此时的栈顶符号为“+”号,优先级低于“*”,因此不输出,进栈。



7. 之后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,因此栈中元素出栈并输出(没有比“+”号更低的优先级,所以全部出栈),总输出表达式为 9 3 1 - 3 * +.然后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。

8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。



9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2

10. 因已经到最后,所以将栈中符号全部出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+



[align=center]五、根据后缀表达计算结果[/align]
后缀表达式:9
3 1-3*+ 10 2/+
[align=center]规则:从左到右遍历表达式的每个数字和符号,遇到是数字就进栈,遇到是符号,就将处于栈顶两个数字出栈,进行运算,运算结果进栈,一直到最终获得结果。[/align]

下面是详细的步骤:

1. 初始化一个空。此桟用来对要运算的数字进出使用。

2. 后缀表达式中前三个都是数字,所以9、3、1进栈。



3. 接下来是减号“-”,所以将栈中的1出栈作为减数,3出栈作为被减数,并运算3-1得到2,再将2进栈。

4. 接着是数字3进栈。



5. 后面是乘法“*”,也就意味着栈中3和2出栈,2与3相乘,得到6,并将6进栈。

6. 下面是加法“+”,所以找中6和9出找,9与6相加,得到15,将15进栈。



7. 接着是10与2两数字进栈。

8. 接下来是符号因此,栈顶的2与10出栈,10与2相除,得到5,将5进栈。



9. 最后一个是符号“+”,所以15与5出找并相加,得到20,将20进栈。

10. 结果是20出栈,栈变为空。



[align=center]六、代码(C语言)[/align]
expresstionComputing.h

#define TRUE         1
#define FALSE        0
#define OK           1
#define ERROR        0
#define INFEASIBLE  -1
#define OVERFLOW    -2
#define STACK_INIT_SIZE  100
#define STACKINCREMENT    10

typedef int Status;

template <class T>
class SqStack{
private:
T *base;
T * top;
int stacksize;
public:
Status InitStack ();
Status Push (T e);
Status Pop (T&e);
Status StackEmpty();
T * getTop();
};

template <class T>
T * SqStack<T>::getTop(){
return top;
}
template <class T>
Status SqStack<T>::InitStack ()
{
base = (T *)malloc(STACK_INIT_SIZE * sizeof(T));
if(!base)
exit (OVERFLOW);
top=base;
stacksize=STACK_INIT_SIZE;
return OK;
}

template <class T>
Status SqStack<T>::Push (T e)
{
if (top-base>=stacksize){
base = (T *)realloc(base,
(stacksize+STACKINCREMENT) * sizeof(T));
if(!base)exit(OVERFLOW);
top=base+stacksize;
stacksize+=STACKINCREMENT;
}
*top++=e;  // *S.top = e       S.top++
return OK;
}

template <class T>
Status SqStack<T>::Pop (T &e)
{
if (top==base)
return ERROR;
e=*--top;
return OK;
}

template <class T>
Status SqStack<T>::StackEmpty()
{
if(top==base)
return TRUE;
else
return FALSE;
}

[align=center]expresstionComputing.cpp[/align]
//本程序包含了两个实例:数制转换和计算表达式的值

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>

#include "expressionComputing.h"

// 比较两个操作符的优先级
/*
-1:op1<op2,op2运算入栈
0:op1 == op2 ,op1出栈
1:op1>op2 , op1出栈
*/
//op1:栈顶元素,op2:中缀表达式中的运算符
int Precedence(char op1, char op2)
{
if (op1 == '(')
{
return -1;
}

if (op1 == '+' || op1 == '-')
{
if (op2 == '*' || op2 == '/')
{
return -1;
}
else
{
return 0;
}
}

if (op1 == '*' || op1 == '/')
{
if (op2 == '+' || op2 == '-')
{
return 1;
}
else
{
return 0;
}
}
}

//把中缀表达式转换成后缀表达式
char *  InfixToSuffix(char * str,int length){
SqStack<char> S;
S.InitStack();
char * InfixExpression = str;
printf("InfixExpression is %s\n",InfixExpression);
char * SuffixExpress = (char *) malloc(3*length* sizeof(char));
int i=0;
char c;
while(*InfixExpression!='\0'){
if(*InfixExpression>='0'  && *InfixExpression <= '9'){
*(SuffixExpress+i) = *InfixExpression;
i++;
//	printf("number %c\n",*InfixExpression);
//printf("SuffixExpress is %s\n" ,SuffixExpress+'\0');
}
else {
//判断运算符的进栈与出栈
*(SuffixExpress+i) =' ';
i++;
if(S.StackEmpty()){
S.Push(*InfixExpression);
//printf("push\n");
}
else if(*InfixExpression == '(') {
S.Push(*InfixExpression);
//printf("push ( \n");
}else if(*InfixExpression == ')'){
S.Pop(c);
while(c != '('){
*(SuffixExpress+i) = c;
i++;
*(SuffixExpress+i) = ' ';
i++;
S.Pop(c);
}
}else if( Precedence(*(S.getTop()-1),*InfixExpression)>=0){
while(Precedence(*(S.getTop()-1),*InfixExpression)>=0){
S.Pop(c);
*(SuffixExpress+i) = c;
i++;
*(SuffixExpress+i) = '  ';
i++;
}
S.Push(*InfixExpression);
}else{
S.Push(*InfixExpression);
}

}
InfixExpression++;

}

*(SuffixExpress+i) = '  ';
i++;

while(!S.StackEmpty()){
S.Pop(c);
*(SuffixExpress+i) = c;
i++;
*(SuffixExpress+i) = '  ';
i++;
}

*(SuffixExpress+i) = '\0';

return SuffixExpress;
}

int  caculateValue(char * SuffixExpress){
SqStack<int> S;
S.InitStack();

int result=0;
int number1;
int number2;
char *op1 = (char *) malloc(sizeof(char)*20);
char  *op2 =  (char *) malloc(sizeof(char)*20);
bool isFirstSpace = true;
int i=0;

while(*SuffixExpress != '\0'){
printf("current char is %c\n",*SuffixExpress);
//把后缀表达式中非运算符的内容都入栈
if(!(*SuffixExpress == '+'  || *SuffixExpress == '-'   || *SuffixExpress == '*'  || *SuffixExpress == '/')){
if(*SuffixExpress == ' '  && isFirstSpace){
//isFirstSpace = false;
SuffixExpress++;
printf("space is not place to stack\n");
continue;
}else if( *SuffixExpress >= '0' && *SuffixExpress <= '9'){
isFirstSpace = false;
printf("this is number!\n");
*(op1+i) = *SuffixExpress;
i++;
printf("pushing char is %c\n",*SuffixExpress);
}else {
//取到一个操作数,并把在存入栈中
isFirstSpace = true;
*(op1+i) = '\0';
S.Push(atoi(op1));
i=0;
printf("number is end!\n");
}

}else{
//从栈中弹出两个数字,然后进行运算
S.Pop(number2);
S.Pop(number1);
switch(*SuffixExpress){
case '+':
S.Push(number1+number2);
break;
case '-':
S.Push(number1-number2);
break;
case '*':
S.Push(number1*number2);
break;

case '/':
S.Push(number1/number2);
break;
}

}
SuffixExpress++;
}

S.Pop(result);
return result;
}

//包括'\0'
int StringLength(char * str){
if(*str == '\0')
return 1;
else
return 1+ StringLength(++str);
}

void main()
{
char str[100];
printf("请输入表达式:");
scanf("%s",str);
printf("suffixExpress:   %s\n",InfixToSuffix(str,StringLength(str)));
printf("result is %d\n",caculateValue(InfixToSuffix(str,StringLength(str))));
getchar();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: