表达式求值算法----栈的应用
2014-09-09 20:40
375 查看
关于表达式求值这个算法:这个算法算是比较基本的算法了,但是应用面也特别广,在写之前查阅了很多资料看了很多前辈写的一些经验确实学到了很多,过程也比较曲折。一开始先是对几个运算符的优先级问题感到头疼。后来又进一步了解到了表达式的转换问题———中缀表达式转换为后缀表达式。因为后缀表达式在计算机计算的时候会比较方便,尽管中缀表达式比较适合人的思维。
下面是摘抄的一些方法:
首先创建栈并置空,然后依次检查中缀表达式每个字符,不同字符按不同情况处理: (1).若是操作数,就直接将存入字符串exp[]中。 (2).若是‘(’则将其压入栈中。
(3).若是‘)’则依次弹栈并存入字符串exp[]中,直到遇到取出和它匹配的‘(’为止,‘(’出栈丢弃。
(4).若是操作符,如果栈空或者该操作符的优先级大于栈顶操作符则将其放入到栈中。如果该操作符的优先级小于等于栈顶操作符则弹出栈中的操作符存入字符串exp[]中,直到该操作符的优先级大于栈顶操作符或栈空,然后将该操作符入栈。
当读到了中缀式的末尾时,如果栈非空则将栈中所有元素依次弹出存入字符串exp[]中,最后见‘\0’存入exp[]中,则exp[]中存储的就是后缀表达式。
下面是我写的源码:
#include<stdio.h>
#include<math.h>
#include<String.h>
#include<stdlib.h>
#define Max 100
struct stack{
char h[Max];
int top;
};
int initStack(stack* s){
if((s=(stack*)malloc(sizeof(stack)))==NULL)
return 1;
s->top=-1;
return 0;
}
int stackFull(stack* s){
if(s->top==Max)
return 1; // 栈满 返回0 未满返回1
else
return 0;
}
int stackEmpty(stack*s){
if(s->top==-1) // 栈空 返回0 未空返回1
return 1;
else
return 0;
}
void push(stack* s,char c){
if(stackFull(s))
printf("the Stack is full");
else
s->h[++(s->top)]==c;
}
void popStack(stack*s,char c){
if(stackEmpty(s))
printf("the Stack is empty");
else
c=s->h[s->top];
--(s->top);
}
char getTop(stack*s,char c){
if(stackEmpty(s)){
printf("the Stack is empty");
return 0;}
else{
c=s->top;
return c;}
}
int setPriority(char e){
int i;
switch('e'){
case'+':
case'-':
i=1;break;
case'*':
case'/':
i=2;break;
case'(':
case')':
i=3;break;
defult:printf("enter data error!\n ");
}
return i;
}
void transform(char h[],char num[]){ // 将中缀表达式转换成为后缀表达式
int i=0,j=0;
char e,f;
stack *optr;
initStack(optr);
e=h[i];
while(e!='\0'){
if(e>'0'&&e<='9'){
num[j]=e;
++j;
}
else if(e=='+'||'-'||'*'||'/'||'('||')'){
if(stackEmpty(optr)||e=='(') push(optr,e);
else if(e==')'){
do{
popStack(optr,f);
num[j++]=f;
}while(!getTop(optr,f)=='('); // 采用do while而不是while是因为这样可以先运行循环体
popStack(optr,f);
}
else if(setPriority(e)>=setPriority(optr->h[optr->top])) {
push(optr,e);}
else if(setPriority(e)<=setPriority(optr->h[optr->top])) {
num[j++]=e;}
}
++i;
e=h[i];
}
}
int main(){
char h[14]="9+(3-1)*3+4-2";
char num[Max];
transform(h,num);
printf("%s",num);
return 0;
}
因为主要是想熟悉栈的应用,所以就没有标准输入。
在写的过程中遇到了一些问题:
1、字符的运算 。因为在一开始考虑数据结构的时候确实遇到了这个问题,一个正常的表达式中是存在字符型和整型两种类型的。但是当我将它放入一个字符数组然后再单独取出运算的时候,发现字符也可以进行四则运算(以%d形式输出)
2、sizeof()。 在initStack()函数中sizeof(somestruct) 的时候发现一个很奇怪的问题,可能我现在还没有学到这一块知识。在网上搜索的时候才知道是关于 内存对齐 的内容。
3、对于运算符优先级的设置问题。这个问题也是奇葩,一开始我自己想的确实头疼,因为几个字符之间的大小对比因为不知道他们的大小也不好直接equal ,后来通过switch(i)设置大小才通过。
4、else if 。 如果else if 过多的话 不妨用switch试试
5、当时是stack的熟悉和运用了
下面是摘抄的一些方法:
首先创建栈并置空,然后依次检查中缀表达式每个字符,不同字符按不同情况处理: (1).若是操作数,就直接将存入字符串exp[]中。 (2).若是‘(’则将其压入栈中。
(3).若是‘)’则依次弹栈并存入字符串exp[]中,直到遇到取出和它匹配的‘(’为止,‘(’出栈丢弃。
(4).若是操作符,如果栈空或者该操作符的优先级大于栈顶操作符则将其放入到栈中。如果该操作符的优先级小于等于栈顶操作符则弹出栈中的操作符存入字符串exp[]中,直到该操作符的优先级大于栈顶操作符或栈空,然后将该操作符入栈。
当读到了中缀式的末尾时,如果栈非空则将栈中所有元素依次弹出存入字符串exp[]中,最后见‘\0’存入exp[]中,则exp[]中存储的就是后缀表达式。
下面是我写的源码:
#include<stdio.h>
#include<math.h>
#include<String.h>
#include<stdlib.h>
#define Max 100
struct stack{
char h[Max];
int top;
};
int initStack(stack* s){
if((s=(stack*)malloc(sizeof(stack)))==NULL)
return 1;
s->top=-1;
return 0;
}
int stackFull(stack* s){
if(s->top==Max)
return 1; // 栈满 返回0 未满返回1
else
return 0;
}
int stackEmpty(stack*s){
if(s->top==-1) // 栈空 返回0 未空返回1
return 1;
else
return 0;
}
void push(stack* s,char c){
if(stackFull(s))
printf("the Stack is full");
else
s->h[++(s->top)]==c;
}
void popStack(stack*s,char c){
if(stackEmpty(s))
printf("the Stack is empty");
else
c=s->h[s->top];
--(s->top);
}
char getTop(stack*s,char c){
if(stackEmpty(s)){
printf("the Stack is empty");
return 0;}
else{
c=s->top;
return c;}
}
int setPriority(char e){
int i;
switch('e'){
case'+':
case'-':
i=1;break;
case'*':
case'/':
i=2;break;
case'(':
case')':
i=3;break;
defult:printf("enter data error!\n ");
}
return i;
}
void transform(char h[],char num[]){ // 将中缀表达式转换成为后缀表达式
int i=0,j=0;
char e,f;
stack *optr;
initStack(optr);
e=h[i];
while(e!='\0'){
if(e>'0'&&e<='9'){
num[j]=e;
++j;
}
else if(e=='+'||'-'||'*'||'/'||'('||')'){
if(stackEmpty(optr)||e=='(') push(optr,e);
else if(e==')'){
do{
popStack(optr,f);
num[j++]=f;
}while(!getTop(optr,f)=='('); // 采用do while而不是while是因为这样可以先运行循环体
popStack(optr,f);
}
else if(setPriority(e)>=setPriority(optr->h[optr->top])) {
push(optr,e);}
else if(setPriority(e)<=setPriority(optr->h[optr->top])) {
num[j++]=e;}
}
++i;
e=h[i];
}
}
int main(){
char h[14]="9+(3-1)*3+4-2";
char num[Max];
transform(h,num);
printf("%s",num);
return 0;
}
因为主要是想熟悉栈的应用,所以就没有标准输入。
在写的过程中遇到了一些问题:
1、字符的运算 。因为在一开始考虑数据结构的时候确实遇到了这个问题,一个正常的表达式中是存在字符型和整型两种类型的。但是当我将它放入一个字符数组然后再单独取出运算的时候,发现字符也可以进行四则运算(以%d形式输出)
2、sizeof()。 在initStack()函数中sizeof(somestruct) 的时候发现一个很奇怪的问题,可能我现在还没有学到这一块知识。在网上搜索的时候才知道是关于 内存对齐 的内容。
3、对于运算符优先级的设置问题。这个问题也是奇葩,一开始我自己想的确实头疼,因为几个字符之间的大小对比因为不知道他们的大小也不好直接equal ,后来通过switch(i)设置大小才通过。
4、else if 。 如果else if 过多的话 不妨用switch试试
5、当时是stack的熟悉和运用了
相关文章推荐
- 数据结构 算法3.4(栈的应用) 表达式求值(stl版and数组模拟版)
- 数据结构习作之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java) (技术含量少许)
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 表达式求值的经典算法
- 数据结构—中缀表达式转后缀表达式算法及实现—栈的应用—计算表达式(C++代码实现)(1)
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- C语言 算数表达式求值(顺序栈应用实例)
- 栈的经典应用之一——表达式求值
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)
- 回顾数据结构之栈的应用-表达式求值
- 经典算法-算术表达式求值
- 写了个表达式求值的算法
- 经典算法-算术表达式求值
- 表达式求值算法的实现
- 栈的一个应用表达式求值
- 表达式求值(栈的应用)(C++)
- 数据结构 栈的应用-- 表达式求值
- 表达式求值,中缀后缀转换,表达式递归直接求值等相关算法的实现
- 经典算法-算术表达式求值
- 数据结构之应用 "栈(Stack)" 实现: 解析算术表达式及计算求值 (C#/Java)