二进制搜索树的列表

时间:2012-03-04 00:29:06

标签: list scheme binary-search-tree

我想创建一个函数inbetweenbst: int int BST -> ilist,用作(inbetweenbst i j t),它生成一个严格在i和j之间的消费BST中所有键的列表。如果t中没有任何带有此范围内键的元素,则该函数应生成一个空列表。假设i≤j

此外,我必须确保运行时间必须为O(n),其中n是t中元素的数量,而不是使用变异。

我提出了以下代码,它基本上将树更改为只有正确的节点:

(define (bst->list t)
  (cond
    [(empty? t) empty]
    [else
     (append (bst->list (BST-left t)) (cons (BST-key t) empty) (bst->list (BST-right t)))]))


(define (list->bst lst)
  (cond
    [(empty? lst) empty]
    [else (make-BST (first lst) empty (list->bst (rest lst)))]))

(define (inbetweenbst i j t)
  (define bst (list->bst (bst->list t)))
  (cond
   [(empty? bst) empty]
   [(and (> (BST-key bst) i) (< (BST-key bst) j))
             (cons (BST-key bst) (inbetweenbst i j (BST-right bst)))]
   [else (inbetweenbst i j (BST-right bst))]))

但我认为我的代码在O(n ^ 2)中运行....任何让它运行O(n)的建议......我很漂亮我不能使用append因为它是O(n)函数,我只限于cons ...我在想法上迷失了,任何建议都有帮助吗? = d

3 个答案:

答案 0 :(得分:2)

我相信程序bst->list可以用这样简单有效的方式编写:

(define (bst->list t)
  (let inorder ((tree t)
                (acc empty))
    (if (empty? tree)
        acc
        (inorder (BST-left tree)
                 (cons (BST-key tree)
                       (inorder (BST-right tree)
                                acc))))))

在上面的代码中,我没有使用append来构建所有键的列表,只有cons个操作。之后,构建一个过滤所需范围内的键的过程应该是微不足道的:

(define (in-between-bst i j t)
  (filter <???>
          (bst->list t)))

编辑:

以下是bst->list程序,未使用let并使用cond代替if

(define (bst->list t)
  (inorder t empty))

(define (inorder tree acc)
  (cond ((empty? tree)
         acc)
        (else
         (inorder (BST-left tree)
                  (cons (BST-key tree)
                        (inorder (BST-right tree)
                                 acc))))))

答案 1 :(得分:1)

首先考虑通过有序遍历将树转换为列表的递归方法。将递归调用的结果附加到树的左子节点,然后是当前节点,然后是对树的右子节点的递归调用的结果;到达空节点时递归停止。

现在将其转换为仅在所需范围内的节点上运行的方法。唯一的区别是,当您到达空节点时,或者当您到达超出所需范围的节点时,递归会停止。

在您的代码中,您已经拥有了第一个函数,名为bst-&gt; list。您所要做的就是修改函数以添加另一个cond子句(在空?之后和else之前),以便在超出所需范围时返回空树。不需要变量bst,这只是t。

答案 2 :(得分:0)

作为消除append调用的提示,考虑一个更简单的函数,它只是将S表达式展平为原子列表。这是天真的版本:

;; flatten : S-expr -> (listof atom)
(define (flatten x)
  (cond [(null? x)
         null]
        [(pair? x)
         (append (flatten (car x))
                 (flatten (cdr x)))]
        [else
         (list x)]))

这是另一个版本。它不使用重复和附加,而是使用一个辅助函数,该函数接受一个额外的参数,该参数包含当前参数右侧所有内容的展平列表。

;; flatten : S-expr -> (listof atom)
(define (flatten x)
  (flatten* x null))

;; flatten* : S-expr (listof atom) -> (listof atom)
(define (flatten* x onto)
  (cond [(null? x)
         onto]
        [(pair? x)
         (flatten* (car x)
                   (flatten* (cdr x) onto))]
        [else
         (cons x onto)]))

您可以将此技术应用于您的问题。