栈的应用--递归与四则运算表达式求值

来源:互联网 发布:snmp 端口 编辑:程序博客网 时间:2024/05/16 14:15

递归

将一个直接调用自己或通过一系列的调用语句间接的调用自己的函数,称为递归函数

每个递归定义必须至少有一个条件,满足是递归将不再进行,即不再引起自身而是返回值退出。(即必须要有递归结束的条件,以数值返回就不再调用函数)

例子–斐波那契数列

Q:若兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对兔子。假设所有兔子都不死,那么一年以后可以繁殖多少对兔子呢?

分析: 第一个月–1对 ; 第二个月–1对 ; 第三个月–2对 ; 第四个月–3对 ; 第五个月–5对 ; 第六个月–8对 ……

斐波那契数列用数学函数来表示:

F0=0,F1=1,Fn=Fn1+Fn2(n>1)

下面先使用常规的迭代方法实现斐波那契数列:

int main(){   int i;   int a[40];   a[0]=1;   a[1]=1;   printf("%d and %d",a[0],a[1]);   for(i=2;i<40;i++){ //确定a[0]和a[1],逐步计算      a[i]=a[i-1]+a[i-2];      printf("%d",a[i]);   }   return 0;}

接下来使用递归方法来实现(简单干净):

/*斐波那契数列的递归实现*/int Fbi(int i){   if(i<2) return i == 0 ? 0 : 1;   return Fbi(i-1)+Fbi(i-2); //递归调用函数本身}int main(){   int i;   for(i=0;i<40;i++)      printf("%d",Fbi(i));   return 0;}

小结

迭代使用的是循环结构,而递归使用的是选择结构。递归会让代码的结构简单、清晰,但是大量的递归调用会建立函数的副本,耗费大量的时间和内存。视情况选择实现方法。

递归和栈的关系:递归过程中退回的顺序是它前行顺序的逆序,编译器使用栈来实现递归操作。当然现在很多高级语言已经系统封装了递归,可直接使用。

四则运算表达式求值

了解–后缀(逆波兰)表达式法

之前也已经有根据括号匹配来完成四则运算,但是还不够,除了括号还要考虑到四则运算的先后顺序,先乘除后加减,所以,后来提出一种不需要括号后缀表达法,也被称为逆波兰表示—–所有的符号都要在运算数字的后面出现。

中缀表达式–后缀表达式法

将中缀表达式“9+(3-1)3+10/2”转化为后缀表达式“9 3 1 - 3*+10 2 / +”。

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

步骤:
1. 初始化空栈,用于符号的进出栈使用;
2. 首先是数字9,输出9;后面是符号“+”,进栈;
3. 第三个符号是(,符号,还未配对,所以进栈;接下来是数字3,输出;
4. 接下来是符号“–”,因前面是左括号,遇到右括号才出栈,所以,入栈;
5. 数字1,输出;遇到右括号“)”,弹出左括号上方的所有符号,所以”–”出栈;
6. 符号”*”,比“+”的优先级高,所以入栈;数字3,输出,这时输出为9 3 1 – 3;
7. 符号”+”,不高于”*”和“+”符号,所以两个符号都弹出,然后将“+”进栈;
8. 数字10,输出;”/”的优先级高于“+”,所以入栈,此时输出为9 3 1 – 3 * + 10;
9. 数字2,输出;到了表达式末尾,所有符号弹栈,最后输出 9 3 1 – 3 * + 10 2 / +。

后缀表达式法计算结果

后缀表达式“9 3 1 - 3**+10 2 / +”,计算其最终结果。

规则:从左到右遍历表达式的每个数字和符号,遇到数字就进栈,晕倒是符号,就将处于栈顶两个元素出栈,进行运算,运算结果进栈,一直到最终获得结果。

步骤:
1. 初始化空栈,用于表达式中数字的进出栈使用;
2. 首先是数字9,3,1,进栈;遇到‘–’号,将数字1和3弹出栈,3-1 运算完成,将数字2入栈;
3. 数字3,入栈;遇到‘*’号,将数字3和2弹出栈,2*3运算完成后,将6压入栈;
4. 接下来,符号‘+’,将数字6和9弹出栈,9+6运算完成后,将15压入栈;
5. 数字10和2,入栈;符号‘/’,将2和10弹出栈,10/2运算完成后,将5入栈;
6. 符号‘+’,将数字5和15弹出栈,15+5运算完成后,将20压入栈;
7. 表达式结尾,将结果20弹出栈,栈为空。

小结

四则表达式求值主要分为两个步骤:首先将中缀表达式变为后缀表达式,这个过程中,将符号出入栈;然后将后缀表达式进行运算,这个过程,将数字出入栈。具体参考上述。

0 0
原创粉丝点击