判断DrRacket中给定代码所属递归类型:structural/acumulative/generative recursion
递归类型分析与代码判断
三种递归的核心差异
- 结构递归(Structural Recursion):完全跟着数据的天然结构走,比如处理列表就递归调用剩余的
cdr部分,处理自然数就用sub1拆成更小的数。递归参数一定是原输入的直接子结构,不需要额外构造参数。 - 累加递归(Accumulative Recursion):依赖一个“累加器”变量存储中间结果,每一步递归都会更新累加器,最终直接返回累加器的值。且递归调用是函数的最后一步操作(尾递归),不需要在递归返回后再做额外计算。
- 生成递归(Generative Recursion):不依赖原始数据的结构,完全根据问题的求解逻辑生成新的递归参数。比如二分查找取中间值、枚举试数,参数不是原数据的子结构,是主动根据策略构造出来的。
你的DrRacket代码分析
先贴出代码:
(define (sqrt/nat x) (local [(define (sqrt/above x t) (if (> (* t t) x) (sub1 t) (sqrt/above x (add1 t))))] (sqrt/above x 1)))
这段代码的逻辑是从t=1开始递增试数,直到t²超过x,返回前一个t(即x的整数平方根)。
结论:属于生成递归
原因如下:
- 不是结构递归:整个递归过程中
x没有被拆解(比如没有对x使用sub1),递归参数(add1 t)和原始输入x的结构没有任何子结构关系,完全是额外构造的。 - 不是累加递归:没有用累加器存储中间结果,递归调用结束后还需要执行
sub1 t的计算,并非直接返回递归结果;全程也没有累积任何中间值,只是不断生成新的t进行尝试。 - 符合生成递归特征:依靠“枚举试数”的策略主动生成下一个参数,每一步的
t都是根据问题逻辑构造的,和原始数据的结构无关。
累加递归与生成递归的核心区别
用实际例子对比更清晰:
- 累加递归示例(计算阶乘):
这里(define (fact n) (local [(define (fact-acc n acc) (if (zero? n) acc (fact-acc (sub1 n) (* n acc))))] (fact-acc n 1)))acc是累加器,每一步把当前n乘到acc中,最终直接返回acc——递归调用是函数的最后一步,无需额外计算。 - 生成递归就是你这段代码,或是二分查找这类逻辑:参数是根据问题求解策略主动构造的,既不是原始数据的子结构,也不需要累加器存储中间结果。
内容的提问来源于stack exchange,提问作者tim123908
相关产品推荐
相关产品推荐

