StackOps

从递归到非递归

跟風遠走 提交于 2021-01-14 00:37:07
递归确实是一种优雅强大的技术, 但是好多代码库都偏爱使用迭代,即使使用递归, 也都往往对递归调用的最大栈深度提前做预估或限制等。可能考虑递归性能一般低于迭代。有些问题,我们可能先是使用递归解决, 然后再转变成对应的迭代版本, 练习递归到迭代的转换,也有助于我们理解问题的递归结构。 树是典型的递归定义数据结构, 对应的操作也是递归的实现,如二叉树的遍历: type node struct { link [2]*node data rune } func preOrder(root *node) { if root != nil { fmt.Printf("%c ", root.data) preOrder(root.link[0]) //left subtree preOrder(root.link[1]) //right subtree } } func inOrder(root *node) { if root != nil { inOrder(root.link[0]) //left subtree fmt.Printf("%c ", root.data) inOrder(root.link[1]) //right subtree } } func postOrder(root *node) { if root != nil { postOrder(root.link[0])

《算法》笔记 16

故事扮演 提交于 2020-02-27 08:51:25
使用正则表达式描述模式 非确定有限状态自动机NFA 模拟NFA的运行 NFA的表示 构造与正则表达式相对应的NFA NFA的模拟与可达性 除了查找子字符串,在很多时候并不知道被查找模式的完整信息,这时就需要用到正则表达式了。正则表达式在子字符串查找、合法性校验、网络爬虫等方面有着非常广泛的应用。 ### 使用正则表达式描述模式 正则表达式对模式的描述,基于几个基本操作。 连接操作,比如AB,表示由A和B连接而成的模式。 或操作,或操作可以在模式中指定多种可能的匹配,用"|"表示。 闭包操作,闭包操作可以把模式部分重复任意次数,用"*"表示。 括号,括号可以改变默认优先级的顺序。 在编程语言中使用的正则表达式还有很多其它语法,但都是基于这几种基本操作的。 ### 非确定有限状态自动机 如何根据正则表达式所描述的模式来匹配文本呢?子字符串查找中使用的有序状态自动机DFA会根据文本中的字符改变自身的状态,但正则表达式匹配比子字符串查找更复杂。因为或操作的存在,自动机无法仅根据一个字符就判断出模式是否出现;再加上闭包的存在,自动机甚至无法知道需要检查多少字符才会匹配失败。为了克服这些困难,需要非确定有限状态自动机NFA。 根据Kleene定理,任意正则表达式都存在一个与之对应的非确定有限状态自动机,反之亦然。所以任意正则表达式都可以转换为一个非确定有限状态自动机