如何从方案中获得两套联合集?

时间:2013-08-08 18:29:08

标签: scheme union racket set

继续上一篇关于交集(How to take intersection of pairs from two lists in scheme?)的帖子,我已经为同一行的联合编写了一个小代码。输出应该是:( union'((1 2)(2 1))'((1 3)(3 4))) - '((1 5)(2 1)(3 4))。但是,我的程序输出并不是我想要的。我认为我的递归或条件需要一些指导。请帮忙。感谢。

(define union
  (lambda (set1 set2)
    (let ((newlist '()))
      (cond ((null? set1) set2)
            ((null? set2) set1)
            ((eq? (caar set1) (caar set2))
             (append newlist (cons (caar set1) (+ (cadr (car set1))(cadr (car set2))))))
            (else 
             (if (> (caar set1) (caar set2))(append newlist (car set1)) (union (cdr set1) set2))
             (union set1 (cdr set2)))))))

1 个答案:

答案 0 :(得分:1)

1)eq?仅当两个参数完全相同的对象时才返回true。如果您只是比较数字,则需要使用equal?=

2)即使你的递归,无论你做什么,newlist都是空的。您只是在最后两种情况下附加一个空列表。

3)这实际上不是联盟。当'(1 2)'(1 3)成为'(1 5)时,您正在寻找一些特殊行为。

然而,这就是你想要的。考虑到您投放了<>并且各个集合中没有重复项(例如'((1 2) (1 2) (3 4))

,我们根据您的列表预先排序的假设进行操作
(define (union set1 set2)
  (cond [(empty? set1) set2]
        [(empty? set2) set1]
        [(equal? (car set1) (car set2)) (cons (car set1) 
                                              (union (cdr set1) (cdr set2)))]
        [(= (caar set1) (caar set2)) (cons (list (caar set1)
                                                 (+ (cadar set1)
                                                    (cadar set2)))
                                           (union (cdr set1) (cdr set2)))]
        [(< (caar set1) (caar set2)) (cons (car set1) (union (cdr set1)
                                                             set2))]
        [else (cons (car set2) (union set1
                                      (cdr set2)))]))

逻辑:

1)其中一个是空的吗?如果是,请返回相应的设置。

2)一组中的第一个列表是否等于另一组中的第一个列表?如果是这样,(cons)将共享列表传递给将两个集合的其余部分传递回联合的结果。

3)两个集合的第一个列表中的第一个元素是否相等?如果是这样,(cons)包含公共第一个元素的列表和第二个元素的总和,将两个集合的其余部分传递回联合的结果。

4)最后两步执行与第一步类似的操作。将带有较小的第一个元素(cons)的集合带到传递两个集合的结果上,减去刚刚提取的列表,然后再回到并集中。

您可以使用重复上的绑定本地定义进行优化,但希望这可以让您了解问题以及可能出错的地方。