SICP 全笔记

Exercise 2.65. Use the results of exercises 2.63 and 2.64 to give O(n) implementations of union-set and intersection-set for sets implemented as (balanced) binary trees.

这里实现的 union-set 与 intersection-set 可以使用前面一小节中的结果。我们知道了一个用有序表来实现的集合的 union-set 与 intersection-set 增长阶为 O(n),所以我们的树可以直接转化为有序表然后进行求交集与并集。树转为表需要 O(n),表转为树需要 O(log(n)),所以整体的阶依然是 O(n)。

(define (union-set set1 set2)
  (define (union-ordered-list lst1 lst2)
    (cond ((null? lst1) lst2)
          ((null? lst2) lst1)
          ((= (car lst1) (car lst2))
           (cons (car lst1)
                 (union-ordered-list (cdr lst1) (cdr lst2))))
          ((> (car lst1) (car lst2))
           (cons (car lst2)
                 (union-ordered-list lst1 (cdr lst2))))
          (else
           (cons (car lst1)
                 (union-ordered-list (cdr lst1) lst2)))))  
  (let ((set1-list (tree->list set1))
        (set2-list (tree->list set2)))
    (list->tree (union-ordered-list set1-list set2-list))))

;;; intersection-set
(define (intersection-set set1 set2)
  (define (intersection-ordered-list lst1 lst2)
    (cond ((or (null? lst1) (null? lst2)) '())
          ((= (car lst1) (car lst2))
           (cons (car lst1)
                 (intersection-ordered-list (cdr lst1) (cdr lst2))))
          ((> (car lst1) (car lst2))
           (intersection-ordered-list lst1 (cdr lst2)))
          (else
           (intersection-ordered-list (cdr lst1) lst2))))  
  (let ((set1-list (tree->list set1))
        (set2-list (tree->list set2)))
    (list->tree (intersection-ordered-list set1-list set2-list))))

测试时,则需要保证生成的树的正确性,如果我们需要使用二叉树来表示,那么我们不得不在生成树的时候使用 sort 过程先排序再转化为树(这是我们之前没有考虑的时间支出的部分)。


(load "../testframe.scm")

; element-of-set?
(asserttrue (element-of-set? 1 (list->tree '(1 2 3))))

(asserttrue (element-of-set? 1 (list->tree '(2 1 3))))

(asserttrue (element-of-set? 1 (list->tree '(2 3 1))))

; adjoin-set
(assertequal? (tree->list (adjoin-set 1 (list->tree '(2 3 4))))
              '(1 2 3 4))

(assertequal? (tree->list (adjoin-set 1 (list->tree '(1 2 3))))
              '(1 2 3))

; intersection-set
(assertequal? (intersection-set (list->tree '(1 2 3)) (list->tree '(4 5 6)))
              '())

(assertequal? (tree->list (intersection-set (list->tree '(1 2 3)) (list->tree '(2 3 4))))
              '(2 3))

(assertequal? (tree->list (intersection-set (list->tree '(1 2 3)) (list->tree '(1 2 3 4))))
              '(1 2 3))

(assertequal? (tree->list (intersection-set (list->tree '(1 2 3 4)) (list->tree '(1 2))))
              '(1 2))

; union-set
(assertequal? (tree->list (union-set (list->tree '(1 2 3)) (list->tree '(3 4 5))))
              '(1 2 3 4 5))

(assertequal? (tree->list (union-set (list->tree '(1 2 3)) (list->tree '(1 2 3 4))))
              '(1 2 3 4))

(assertequal? (tree->list (union-set (list->tree '(1 2 3 4)) (list->tree '(1 2 3))))
              '(1 2 3 4))

(assertequal? (tree->list (union-set (list->tree '(1 2 3)) (list->tree '(4 5 6))))
              '(1 2 3 4 5 6))