So, you don't mind slow and just want a choice-based approach, huh? Here we go....
First, we define the select1 function, which receives the minimum (or maximum) element, followed by all other elements. For linked lists, this is probably the easiest approach, easier than trying to implement (say) quickselect.
(define (select1 lst cmp?) (let loop ((seen '()) (rest lst) (ext #f) (extseen '())) (cond ((null? rest) (cons (car ext) (append-reverse (cdr extseen) (cdr ext)))) ((or (not ext) (cmp? (car rest) (car ext))) (let ((newseen (cons (car rest) seen))) (loop newseen (cdr rest) rest newseen))) (else (loop (cons (car rest) seen) (cdr rest) ext extseen)))))
Now actually weaving:
(define (zippy lst) (let recur ((lst lst) (left? #t)) (if (null? lst) '() (let ((selected (select1 lst (if left? < >)))) (cons (car selected) (recur (cdr selected) (not left?)))))))
This approach is O (n²), while the sorting and rotation approach recommended by everyone else is O (n log n).
source share