栈在括号匹配中的应用
#define MaxSize 10
typedef struct{
char data[MaxSize];
int top;
}SqStack;
//初始化栈
void InitStack(SqStack &S);
//进栈
bool Push(SqStack &S,char s);
//出栈
bool Pop(SqStack &S,char &s);
//判空
bool EmptyStack(SqStack &s);
//括号换边
char bracketReSide(char bracket){
if(bracket == ')')return '(';
if(bracket == ']')return '[';
if(bracket == '}')return '{';
return '1';
}
//括号匹配
bool bracketCheck(char str[], int length){
SqStack I;
InitStack(&I);
for(int i = 0;i < length; i++){
if(str[i] == '{' || str[i] == '[' || str[i] == '('){
Push(S,str[i]);
}else{
if(StackEmpty(S))return false;
char topChar;
Pop(SqStack,&topChar);
if(topchar != bracketReSide(str[i]))return false;
}
}
return StackEmpty(I);
}
表达式求值
- 前缀表达式
- 中缀表达式
- 后缀表达式
中缀表达式转后缀表达式
中缀表达式由三部分组成{操作符,运算符,界限符}
手算方法
- 确定中缀表达式中各个运算符的运算顺序(运算顺序不唯一,因此对应的后缀表达式不唯一)
- 选择下一个运算符,按照[左操作数 右操作数 运算符]的方式组成一个新的操作数
- 如果还有运算符没被处理,就继续2
解决运算结果不唯一问题:左优先原则——只要左边的运算符能先运算,就优先处理左边的运算
中缀转前缀:右优先原则
后缀表达式求值
手算方法
对于输入的表达式字符串:
从左往右扫描,每遇到一个运算符,就让运算符前面的两个操作数进行运算,并合并成一个操作数
栈在递归当中的应用
函数调用栈
//求n!
int Factorial(int n)
{
if(n == 0 ||n == 1)return 1;
return n*Factorial(n-1);
}
//求Fib
int Fib(int n){
if(n == 0)return 0;
else if(n == 1)return 1;
else return Fib(n - 2) + Fib(n - 1);
}
函数调用的特点:最后被调用的函数最先执行结束(LIFO)
函数调用时,需要用一个“函数调用栈”存储:
- 调用返回地址
- 实参
- 局部变量
递归调用时,函数调用栈可称为“递归工作栈”
每进入一层递归,就将递归调用所需要的信息压入栈顶
每推出一层递归,就从栈顶弹出相应信息
缺点:效率低,太多层递归可能会导致栈溢出,可能包含多次重复运算
可以自定义栈将递归算法改成非递归算法