1 ;;; "sort.scm" Defines: sorted?, merge, merge!, sort, sort!
2 ;;; Author : Richard A. O'Keefe (based on Prolog code by D.H.D.Warren)
4 ;;; This code is in the public domain.
6 ;;; Updated: 11 June 1991
7 ;;; Modified for scheme library: Aubrey Jaffer 19 Sept. 1991
8 ;;; Updated: 19 June 1995
10 ;;; (sorted? sequence less?)
11 ;;; is true when sequence is a list (x0 x1 ... xm) or a vector #(x0 ... xm)
12 ;;; such that for all 1 <= i <= m,
13 ;;; (not (less? (list-ref list i) (list-ref list (- i 1)))).
15 (define (sort:sorted? seq less?)
20 (let ((n (vector-length seq)))
25 (less? (vector-ref seq i)
26 (vector-ref seq (- i 1))))
29 (let loop ((last (car seq)) (next (cdr seq)))
31 (and (not (less? (car next) last))
32 (loop (car next) (cdr next)) )) )) ))
36 ;;; takes two lists a and b such that (sorted? a less?) and (sorted? b less?)
37 ;;; and returns a new list in which the elements of a and b have been stably
38 ;;; interleaved so that (sorted? (merge a b less?) less?).
39 ;;; Note: this does _not_ accept vectors. See below.
41 (define (sort:merge a b less?)
45 (else (let loop ((x (car a)) (a (cdr a)) (y (car b)) (b (cdr b)))
46 ;; The loop handles the merging of non-empty lists. It has
47 ;; been written this way to save testing and car/cdring.
51 (cons y (loop x a (car b) (cdr b)) ))
55 (cons x (loop (car a) (cdr a) y b)) )) )) ))
58 ;;; (merge! a b less?)
59 ;;; takes two sorted lists a and b and smashes their cdr fields to form a
60 ;;; single sorted list including the elements of both.
61 ;;; Note: this does _not_ accept vectors.
63 (define (sort:merge! a b less?)
65 (if (less? (car b) (car a))
76 (loop a (cdr a) b)) )) )
80 ((less? (car b) (car a))
85 (else ; (car a) <= (car b)
93 ;;; (sort! sequence less?)
94 ;;; sorts the list or vector sequence destructively. It uses a version
95 ;;; of merge-sort invented, to the best of my knowledge, by David H. D.
96 ;;; Warren, and first used in the DEC-10 Prolog system. R. A. O'Keefe
97 ;;; adapted it to work destructively in Scheme.
99 (define (sort:sort! seq less?)
103 (let* ((j (quotient n 2))
107 (sort:merge! a b less?)))
112 (set! seq (cddr seq))
113 (if (less? y x) (begin
115 (set-car! (cdr p) x)))
116 (set-cdr! (cdr p) '())
126 (let ((n (vector-length seq))
128 (set! seq (vector->list seq))
129 (do ((p (step n) (cdr p))
132 (vector-set! vec i (car p)) ))
133 ;; otherwise, assume it is a list
134 (step (length seq)) ))
136 ;;; (sort sequence less?)
137 ;;; sorts a vector or list non-destructively. It does this by sorting a
138 ;;; copy of the sequence. My understanding is that the Standard says
139 ;;; that the result of append is always "newly allocated" except for
140 ;;; sharing structure with "the last argument", so (append x '()) ought
141 ;;; to be a standard way of copying a list x.
143 (define (sort:sort seq less?)
145 (list->vector (sort:sort! (vector->list seq) less?))
146 (sort:sort! (append seq '()) less?)))
150 (define sorted? sort:sorted?)
151 (define merge sort:merge)
152 (define merge! sort:merge!)
153 (define sort sort:sort)
154 (define sort! sort:sort!)