您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法系列-栈-栈的应用

2013-11-10 21:51 260 查看

1:算术表达式的计算

表达式求值是编译系统中的一个基本问题,目的是把我们平时书写的算术表达式变成计算机能够理解并能正确求值的表达式。

算术表达式中包含算术运算符和操作符。在运算的时候必须按优先级运算。因此,进行表达式运算时,必须设置两个栈,一个栈用于存放运算符,另外一个用于存放操作符。

大家可以看下这边文章 。利用堆栈求解算术表达式

栈的应用举例:数制转换,表达式求值 代码来自http://blog.sina.com.cn/s/blog_6f5235a10100z1b7.html

#include <stdio.h>
#include <malloc.h>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -2
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef char SElemType;
typedef char Status;
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
Status InitStack(SqStack *S){
//构造一个空栈S
S->base =(SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if(!S->base ) exit(OVERFLOW); //存储分配失败
S->top =S->base ;
S->stacksize =STACK_INIT_SIZE;
return OK;
} //InitStack
Status GetTop(SqStack *S){
SElemType e;
if(S->top==S->base ) return ERROR;
e=*(S->top -1);
return e;
}//GetTop
Status Push(SqStack *S,SElemType e){
//插入元素e为新的栈顶元素
if(S->top-S->base>=S->stacksize  ) { //栈满,追加存储空间
S->base =(SElemType *)realloc (S->base ,(S->stacksize +STACKINCREMENT) * sizeof(SElemType));
if(!S->base ) exit(OVERFLOW);
S->top =S->base +S->stacksize ;
S->stacksize +=STACKINCREMENT;
}
*S->top ++=e;
return OK;
}//Push
Status Pop(SqStack *S,SElemType *e){
//若栈不为空,则删除S的栈顶元素,用E返回其值,并返回OK;否则返回ERROR
if(S->top==S->base ) return ERROR;
e=--S->top ;
return (*e);
}//Pop
Status StackEmpty(SqStack *S){
if(S->base==S->top) return TRUE;
else return FALSE;
}//StackEmpty
SElemType Precede(SElemType i,SElemType j){
int a, b;char c;
char s[7][7]={{'>','>','<','<','<','>','>'},{'>','>','<','<','<','>','>'},{'>','>','>','>','<','>','>'},
{'>','>','>','>','<','>','>'},{'<','<','<','<','<','=',' '},{'>','>','>','>',' ','>','>'},{'<','<','<','<','<',' ','='}};
//算符间优先关系
switch (i){
case '+':
a=0;break;
case '-':
a=1;break;
case '*':
a=2;break;
case '/':
a=3;break;
case '(':
a=4;break;
case ')':
a=5;break;
case '#':
a=6;break;
}
switch (j){
case '+':
b=0;break;
case '-':
b=1;break;
case '*':
b=2;break;
case '/':
b=3;break;
case '(':
b=4;break;
case ')':
b=5;break;
case '#':
b=6;break;
}
c=s[a][b];
return c; //返回优先级权值
}
Status Operate(SElemType a,SElemType theta,SElemType b){
//求算数表达式的值
int c,x,y;
switch (theta){
case '+':
x=(int)a-48; //或x=(int)(a-'o')
y=(int)b-48;
c=x+y+48;
return (char)c;
break;
case '-':
x=(int)a-48;
y=(int)b-48;
c=x-y+48;
return (char)c;
break;
case '*':
x=(int)a-48;
y=(int)b-48;
c=x*y+48;
return (char)c;
break;
case '/':
x=(int)a-48;
y=(int)b-48;
c=x/y+48;
return (char)c;
break;
}
}
char  EvaluateExpress(){
//算数表达式求值的算符优先算法,设OPTR和OPND分别为运算符栈和运算数栈
SqStack OPTR,OPND;
char c,a,b,x,theta;
c=' ';
InitStack(&OPTR);Push(&OPTR,'#');
InitStack(&OPND);
printf("\n请输入要计算的表达式");
c=getchar();
while(c!='#'||GetTop(&OPTR)!='#'){
if(c>'0'&&c<'9'){
Push(&OPND,c);c=getchar();//不是运算符进运算数栈
}
else
switch(Precede(GetTop(&OPTR),c)){
case '<': //栈顶元素优先权低
Push(&OPTR,c);c=getchar();
break;
case '=': //脱冒号并接收下一个字符
Pop(&OPTR,&x);c=getchar();
break;
case '>': //退栈并将运算结果入栈
theta=Pop(&OPTR,&theta);
b=Pop(&OPND,&b);
a=Pop(&OPND,&a);
Push(&OPND,Operate(a,theta,b));
break;
} //switch
} //while
return GetTop(&OPND);
} //EvaluateExpress


2:中缀表达式转换成后缀表达式

算术表达式有两种形式

中缀算术表达式: 6-8/4+3*5

后缀表达式:(将运算符置于两个操作数的后面):20 10 2 3 + / 2

将中缀表达式转换成后缀表达式

(1): 将@压入运算符栈

(2)若遇到操作数 直接输出 并输入一个空格作为两个操作数的分隔符

(3)若遇到操作符 则必须与栈顶比较 运算级别比栈顶高的则进栈 否则退出栈顶元素并输出 然后输出一个空格作为分隔符

(4)若遇到左括号 进栈 若遇到右括号 则一直退栈输出, 直到退到左括号为止

(5)当栈空时 输出的结果即为后缀表达式

中缀表达式转后缀表达式C++代码

3:函数递归的实现

求阶乘

int suml(int n){
if(n==0)
return 1
else
return (n * suml(n-1))
}


递归函数的实现
1:系统首先为递归调用建立一个工作栈,在该工作栈中存放参数、局部变量和调用后的返回地址等信息
2:在每次递归调用之前,把本次算法中所使用的参数、局部变量的当前值和调用后的返回地址等压入栈顶
3:在每次调用递归结束之后,又把栈顶元素弹出,分别赋予相应的参数和局部变量,以便使他们恢复到调用前的状态,然后返回由返回地址所指定的位置
4:继续执行后续指令

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: