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

递归

我们先说递归,在定义上来讲:我们把一个直接调用自己或者通过一系列的调用语句间接调用自己的函数,称为递归函数。

我们应该还记得一个非常有名的数列:斐波那契额数列。在这里一起回忆下:假如兔子在出生两个月后就具有繁殖能力,而且一对兔子每个月能生出一对小兔子,并且假设所有兔子都不会死,那么一年以后总共有多少兔子呢?十年呢?

在这里,很容易发现的一个规律是:前两项之和等于后一项

其数学表达式为:


其代码实现非常的简洁:(我就不写注释了)


谈谈自己对递归的理解:

首先,如果某个问题你考虑用递归来解决,应该如何判断其是否适合?

- 这个问题是否能拆解为许多逻辑完全一致的小问题?

- 这个问题是否具有终止条件?

如果这两个条件都满足了,这个问题应该是可以用递归解决的,但是,递归又容易出现其他的问题,比如:

堆栈溢出,重复计算等等(不多说,坑大家一起踩,嘻嘻)

堆栈溢出的一种解决方案时限定递归条件,比如说限定其递归到哪一层就结束并返回。但是这种方案时有局限性的,只适合预估最大递归深度层数较少的时候。

重复计算是指在递归的过程中,同一个递归函数被计算了多次:比如在斐波那契额数列中,F(4)的计算需要用到F(3),F(5)的计算也需要用到F(3),如果递归层数足够多,是非常消耗资源的。

对于重复计算,一种解决方案是:将计算过的F(n)保存在一个散列表中,在递归过程中,检查F(k)是否被计算过,如果是,则直接从散列表中返回。

四则运算表达式求值

我们要计算:6 + (4 - 1)* 2 - 8 / 2很简单,口算就可以很快算出来(其中的“/”为除以),但是,计算机时怎么算的你知道吗?这时候,栈这种数据结构又派上用场了!

在了解计算机如何计算之前,我们先来缅怀一下想出一种不需要括号的后缀表达法而又没有以他的名字命名的波兰逻辑学家:Jan Lukasiewicz(可能是由于名字太复杂了),这种表示法被后人称为:逆波兰表示

如果以上式子用后缀表达法应该表示成什么形式呢?

6 4 1 - 2 * + 8 2 / -    ,我们称这种式子为后缀表达式

我们先来看看计算机是如何通过这个后缀表达式来计算的:

1. 初始化一个空栈,用以存储表达式上的数字和符号;

2. 表达式的6 4 1都是数字,依次进栈;

3. 下一个为符号“-”,便两次取出栈顶元素,使得1为减数,4为被减数,计算后结果为3,并将3入栈;

4. 然后是数字2,进栈;

5. 接着是符号 * ,则两次取出栈顶元素,将3 和 2做乘法运算,得到 6,将6进栈;

6. 接下来是符号“ + ”,则两次取出栈顶元素,将6 和 6做加法预算,得到12,并将12进栈;

7. 下一个是数字8 和 2,依次进栈;

8. 接着是符号“/”,则两次取出栈顶元素,将2视为除数,将8视为被除数,计算结果为4,将4进栈;

9. 最后是符号“-”,两次取出栈顶元素,计算12 - 4,结果为8;

10. 结果8出栈,栈变为空;

示意图如下:(灵魂画手)


理解了计算及如果通过栈求四则运算表达式的值,我们来谈谈这个逆波兰表示

我们先约定(其实本来就这样叫),6 + (4 - 1)* 2 - 8 / 2这种给人看的叫:中缀表达式

而6 4 1 - 2 * + 8 2 / - 这种给计算机看的叫:后缀表达式

转化规则为:

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

是不是看完之后有种:“你尽管讲,看得懂算我输!”的感觉?没关系,我们一步步来说,就拿上一个例子:

1. 初始化一个空栈,用来存储数字和符号;

2. 第一个数字是6,直接输出;此时输出为:6

3. 后一个是符号“+”和符号“(”,直接依次进栈;

4. 接着是数字 4 ,直接输出;此时输出为:6 4

5. 下一个是减号“-”,进栈,因为“-”的优先级比“(”低;后面是数字“1”,直接输出;此时输出为: 6 4 1

6. 后一个是右括号“)”,有右括号则输出栈顶元素“-”,直到左括号“(”出栈为止(注意:括号并不输出);此时输出为 6 4 1 -

7. 接下来是乘号“*”,进栈,因为优先级高于栈顶符号“+”;紧接着是数字2,直接输出;此时输出为:6 4 1 - 2

8. 接着是符号“-”,其优先级低于栈顶符号“*”,则将栈顶符号出栈,将“-”与栈顶元素比较;并且此时符号“-”的优先级并不比栈顶元素“+”高,则将“+”输出,将“-”入栈;此时输出为: 6 4 1 - 2 * +

9. 接着是数字8,直接输出;后面是符号“/”,直接进栈;此时输出为:6 4 1 - 2 * + 8

10. 接着是数字2,直接输出;此时输出为:6 4 1 - 2 * + 8 2

11. 将栈中元素依次输出;此时输出为:6 4 1 - 2 * + 8 2 / -

绕晕了?

灵魂画手又来了:


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,110评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,443评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,474评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,881评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,902评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,698评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,418评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,332评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,796评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,968评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,110评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,792评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,455评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,003评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,130评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,348评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,047评论 2 355

推荐阅读更多精彩内容