摘至《数据结构教程》第三版。
摘要如下:
堆栈的应用举例:
(1).符号匹配检查;
(2).数制转换;
(3).堆栈在递归中的应用。
一.符号匹配检查
情景:编译程序在检查源程序的语法时,常常由于缺少一个符号引起编译程序列出上百行的诊断信息,而真正的错误却往往没有找到。在这种情况下,一个有用的工具就是检验是否每件事情都能够成对出现的一个程序。而这个程序算法中就要用到一个堆栈。为了简单起见,仅以花括号和园括号为例进行检验,并忽悠出现的任何其他字符。
算法核心思想如下:创建一个空的堆栈,依次读入字符直到文件的末尾,如果读得的字符为左花括号或者左圆括号,则将其压入堆栈。如果读到的字符是右花括号或者右圆括号,则退出当前栈顶元素。读到文件末尾,若堆栈为空,则无错误。
注:(1)如果读到的字符是右花括号或者右圆括号,而此时堆栈为空,则出现不匹配现象,报告错误;(2)如果退出当前栈顶符号不是对应的左花括号或者左圆括号,则出现不匹配,报告错误;(3)读到文件末尾,若堆栈非空,则报告错误。
二.数制转换
场景:对于给定的任意无符号十进制整数num,如何依次输出与其等值的八位进制数的各位数字。
逻辑步骤:①将num除以8,取其余数。②判断商是否为零:a)若商为零,则转换到此结束;b)若商不为零,则将商送num,转到第①步。
例: 把十进制数391转换为八进制数607,其计算过程如下:
步骤 num num/8(商) num%8(余数)
1 391 48 7
2 48 6 0
3 6 0 6
若堆栈采用顺序存储结构,则算法如下:
void CONVERSION(int num){
int STACK[M],top=-1;
do{
STACK[++top]=num%8;
num=num/8;
}while(num!=0);
while(top>=0)
printf("%d",STACK[top--]);
}
若堆栈采用链式存储结构,则算法如下:
void CONVERSION(int num){
STLink p,top =null;
do{
p = (STLink)malloc(sizeof(STNode));
p->data=num%8;
p->link=top;
top=p;
num=num/8;
}while(num!=0);
while(top!=null){
p=top;
printf("%d",p->data);
top=top->link;
free(p);
}
}
三.堆栈在递归中的应用
概念:①在算法设计过程中,把一个通过算法调用语句直接或者间接调用自己的算法称为递归算法;②直接递归:自己调用自己的过程;③通过另一个(或几个)算法来间接调用自己的过程称为间接递归。
递归过程的实现
一般说来,在计算机中实现程序的调用可分为如下3个步骤。
①保存调用信息,其中主要是返回地址信息和实参信息;
②分配调用过程中所需要的数据区;
③把控制转移到被调用过程的入口。
当被调用算法运行结束需要返回到调用算法时,一般也分为以下3个步骤:
①保存返回时的有关信息,如计算结果等;
②释放被调用算法占用的数据区;
③把执行控制按调用时保存的返回地址转移到调用算法中调用语句的下一条语句。
从递归算法到非递归算法的转换