Recursion SICP 2.64递归过程的增长阶

Recursion SICP 2.64递归过程的增长阶,recursion,tree,scheme,sicp,Recursion,Tree,Scheme,Sicp,我在自学SICP,很难找到递归函数的增长顺序 以下过程列表->树将有序列表转换为平衡搜索树: (define (list->tree elements) (car (partial-tree elements (length elements)))) (define (partial-tree elts n) (if (= n 0) (cons '() elts) (let ((left-size (quotient (- n 1) 2)))

我在自学SICP,很难找到递归函数的增长顺序

以下过程列表->树将有序列表转换为平衡搜索树:

(define (list->tree elements) 
  (car (partial-tree elements (length elements)))) 

(define (partial-tree elts n) 
  (if (= n 0) 
      (cons '() elts) 
      (let ((left-size (quotient (- n 1) 2))) 
        (let ((left-result (partial-tree elts left-size))) 
          (let ((left-tree (car left-result)) 
                (non-left-elts (cdr left-result)) 
                (right-size (- n (+ left-size 1)))) 
            (let ((this-entry (car non-left-elts)) 
                  (right-result (partial-tree (cdr non-left-elts) 
                                              right-size))) 
              (let ((right-tree (car right-result)) 
                    (remaining-elts (cdr right-result))) 
                (cons (make-tree this-entry left-tree right-tree) 
                      remaining-elts))))))))
我一直在网上查看解决方案,我认为以下网站提供了最好的解决方案,但我很难理解它:

我的理解是,过程“partial tree”每次调用时都会重复调用三个参数,分别是“this entry”、“left tree”和“right tree”。(只有在必要时才使用“剩余ELT”-无论是在第一个“部分树”调用中还是在调用“非左ELT”时)

  • 此条目调用:car、cdr和cdr(左结果)
  • 左入呼叫:car、cdr和自身,每一步长度减半
  • 右项调用:car,本身以cdr(cdr(left result))作为参数,长度减半
  • “left entry”将有基本的2个日志(n)步骤,所有三个参数分别调用“left entry”。 所以它会有三元树状结构,我认为总的步骤数类似于3^log(n)。但是解决方案说它只使用每个索引1..n一次。但“this entry”是否会将每个节点上的相同索引减少为“right entry”

    我很困惑。。 此外,在第(a)部分中,解决方案网站声明:

    “在非终止情况下,部分树首先计算数字 应该进入平衡二进制文件左子树的元素的 大小为n的树,然后调用包含元素的部分树 值,该值同时生成这样的子树和元素列表 然后将未使用元素的头作为 “当前节点的值”

    我相信程序会在离开树之前完成此项。为什么我错了

    这是我第一本关于CS的书,我还没有接触到主定理。 在一些解决方案中提到了这一点,但希望我能够不用它来回答这个问题

    感谢您的阅读,我期待着您的回复


    Chris

    您需要了解
    如何让表单工作。在

              (let ((left-tree (car left-result)) 
                    (non-left-elts (cdr left-result))
    
    左树
    不调用任何东西。它被创建为一个新的词汇变量,并被赋值为
    (car left result)
    。其周围的括号仅用于将描述由
    let
    形式引入的一个变量的元素组合在一起:变量的名称及其值:

              (let (  (   left-tree      (car left-result)  ) 
              ;;      ^^                                   ^^
                      (   non-left-elts  (cdr left-result)  )
              ;;      ^^                                   ^^
    

    下面是如何理解递归过程的工作原理:不要

    只是不要试图去理解它是如何工作的;相反,分析它做什么,假设它做(对于较小的情况)它应该做什么

    在这里,
    (部分树elts n)
    接收两个参数:元素列表(大概放在树中)和列表长度。它返回

    树的cons对-转换的结果,以及最顶端调用中的剩余元素(如果length参数正确的话),这些元素应该没有剩余

    现在我们知道了它应该做什么,我们看看里面。事实上,假设上面所说的是完全有意义的:将元素数量减半,处理列表,将树和剩余列表取回(现在为非空),然后处理剩下的内容

    此条目
    不是树-它是树节点中的元素:

                (let ((this-entry (car non-left-elts)) 
    
    背景

                      (right-size (- n (+ left-size 1))
    
    意味着
    n==右尺寸+1+左尺寸
    。这是进入节点本身的1个元素,
    this entry
    元素


    由于每个元素直接进入其节点一次,该算法的总运行时间与输入列表中的元素数成线性关系,使用对数堆栈空间。

    您的解决方案和第64页的let表达式定义的重新阅读清楚了这一点。我很高兴看到你的回答,谢谢。(如果我以前没有说过这句话,)不客气
                      (right-size (- n (+ left-size 1))