间接递归的实际应用
practical application of indirect recursion
在一次采访中,他们要求我"给出一些间接递归的实际应用"。我刚刚回答了直接递归和间接递归之间的区别。我用谷歌搜索,但仍然没有得到任何令人满意的答案。
非常欢迎有关此主题的任何信息。
间接递归的一个明显例子是递归下降解析器。
举个简单的例子,考虑一个语法,如下所示:
expression = product (+|-) product
product = term (*|/) term
term = number | variable | '(' expression ')'
为了使用递归下降解析器解析该语法,我们基本上创建了一个函数来表示每个元素:
expression(input) {
product(input);
assert(operator(input) == '-' || '+');
product(input);
}
product(input) {
term(input);
assert(operator(input) == '/' || '*');
term(input);
}
term(input) {
if (next(input) == '(')
expression(input);
// ...
}
我显然在这里简化了很多,但希望总体思路是:表达式由+
或-
组合的产品组成。产品由由/
或*
组合的术语组成。术语是括在括号中的数字、变量或表达式。我们调用一个函数来识别其中的每一个,所以当我们将括号中的表达式识别为术语时,我们使用间接递归 - expression()
-> product()
-> term()
-> expression()
。
顺便说一句,我以相互递归的名义知道它。
它可以用来模拟有限自动机,但前提是语言实现了尾部调用优化,这意味着当一个递归调用终止时,返回语句仅由另一个递归调用组成,该递归调用重用当前堆栈帧。如果没有这种优化,相互递归很容易导致堆栈溢出(双关语...好吧:-)。
更明确地说,这里有一个 Lua 脚本,用于识别输入字符串中字符串111
的第一次出现。每个函数代表有限自动机的状态,状态转换通过相互递归调用来模拟(Lua执行适当的尾部调用优化,因此即使对于更长的输入字符串也不会发生堆栈溢出)。C++相同的技术不适用,因为标准(AFAIK)不能保证正确的尾部调用优化。如果你不了解Lua,把它当作伪代码(它是相当可读的,因为它有一个类似Pascal的语法)。无论如何,您可以在现场演示中剪切和粘贴代码。
function Init( input, pos )
if pos > #input then return 0 end
local bit = input:sub( pos, pos )
if bit == "0" then
return Got0( input, pos + 1 )
else
return Got1( input, pos + 1 )
end
end
function Got0( input, pos )
if pos > #input then return 0 end
local bit = input:sub( pos, pos )
if bit == "0" then
return Got0( input, pos + 1 )
else
return Got1( input, pos + 1 )
end
end
function Got1( input, pos )
if pos > #input then return 0 end
local bit = input:sub( pos, pos )
if bit == "0" then
return Got0( input, pos + 1 )
else
return Got11( input, pos + 1 )
end
end
function Got11( input, pos )
if pos > #input then return 0 end
local bit = input:sub( pos, pos )
if bit == "0" then
return Got0( input, pos + 1 )
else
print( "recognized 111 sequence at position " .. pos - 2 )
print( input )
print( (" "):rep( pos - 3 ) .. "^" )
return 1
end
end
Init( "1101101101110110101", 1 )
相关文章:
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 如何将记忆应用于此递归函数?
- 递归应用 C++20 范围适配器会导致编译时无限循环
- 执行递归函数时 C++ 应用程序崩溃
- 在不使用递归的情况下将 FFT 应用于两个非常大的数字的乘法
- 在 std::函数上递归应用 std::bind 的问题
- 难以理解此应用程序中的递归
- 运算符>的递归应用
- 间接递归的实际应用
- 启发式算法在递归回溯中的应用