具有有序输出的Scheme中的电源设置

时间:2014-04-23 20:16:10

标签: sorting scheme

所以我熟悉使用Scheme创建功率集的算法,如下所示:

 (define (power-set set) 
    (if (null? set) '(()) 
       (let ((power-set-of-rest (power-set (cdr set)))) 
             (append power-set-of-rest 
                   (map (lambda (subset) (cons (car set) subset)) 
                         power-set-of-rest)))))

因此,对于(1,2,3,4),将输出:

(() (4) (3) (3 4) (2) (2 4) (2 3) (2 3 4) (1) (1 4) (1 3) (1 3 4) (1 2) (1 2 4) 
 (1 2 3) (1 2 3 4))

我需要弄清楚如何“按顺序”输出功率组,例如:

(() (1) (2) (3) (4) (1 2) (1 3) (1 4) (2 3) (2 4) (3 4) (1 2 3) (1 2 4) (1 3 4) 
(2 3 4) (1 2 3 4))

进行一些研究,似乎最好的选择是在输出之前运行排序。我不允许使用内置的排序,所以我找到了一些排序列表的示例排序:

(define (qsort e)
  (if (or (null? e) (<= (length e) 1)) 
    e
    (let loop ((left  null)    (right null)
               (pivot (car e)) (rest  (cdr e)))
      (if (null? rest)
         (append (append (qsort left) (list pivot)) (qsort right))
         (if (<= (car rest) pivot)
            (loop (append left (list (car rest))) right pivot (cdr rest))
            (loop left (append right (list (car rest))) pivot (cdr rest)))))))

我无法弄清楚如何根据其中一个电源组中的第二个或第三个元素对其进行排序。任何人都可以提供一个例子吗?

2 个答案:

答案 0 :(得分:2)

这是一个powerset函数,它以正确的顺序返回项目,而不进行排序。它需要Racket并使用其队列来实现广度优先处理:

(require srfi/1 data/queue)
(define (powerset items)
  (define fifo (make-queue))
  (enqueue! fifo (cons '() items))
  (let loop ((result '()))
    (if (queue-empty? fifo)
        (reverse result)
        (let* ((head-entry (dequeue! fifo))
               (subset     (car head-entry))
               (rest-items (cdr head-entry)))
          (pair-for-each (lambda (next-items)
                           (enqueue! fifo (cons (cons (car next-items) subset)
                                                (cdr next-items))))
                         rest-items)
          (loop (cons (reverse subset) result))))))

我们维护一对FIFO队列,每个队列包含一个子集(按相反的顺序)和一个未包含在其中的项目列表,从一个空子集开始,因此所有原始项目仍未包含在其中。

对于每个这样的对,我们将子集收集到结果列表中,并通过从未包含的项中的每个项扩展该子集来扩展队列。队列为空时处理停止。

因为我们每次只将一个元素扩展为一个元素,并且按顺序,结果也是有序的。

答案 1 :(得分:1)

这是一个适合您需求的比较功能。它假定两个输入参数中的数字已经排序。

(define (list-less? lst1 lst2)

  ;; Compare the contents of the lists.
  (define (helper l1 l2)

    ;; If two lists are identical, the answer is false.
    ;; This scenario won't be exercised in the problem.
    ;; It's here only for the sake of completeness.
    (if (null? l1)
      #f

      ;; If the first item of the second list is greater than
      ;; the first item, return true.
      (if (> (car l2) (car l1))
        #t
        (or (< (car l1) (car l2)) (helper (cdr l1) (cdr l2))))))

  ;; First compare the lengths of the input arguments.
  ;; A list of smaller length are assumed to be "less"
  ;; than list of greater length.
  ;; Only when the lists are of equal length, do we
  ;; compare the contents of the lists.
  (let ((len1 (length lst1)) (len2 (length lst2)))
    (if (> len1 len2)
      #f
      (or (< len1 len2) (helper lst1 lst2)))))