SORTING BY SHELL'S ALGORITHM

Since the Shell sort makes frequent non-sequential accesses to elements of the data structure, only a (destructive) vector version is offered here.

The body of the Shell sort is a nested loop. The outer loop controls the size of the gap, which must decrease monotonically to 1 for the sort to work; Robert Sedgewick's Algorithms recommends gap sizes in the series 1, 4, 13, 40, 121, ..., in which each term is thrice its predecessor plus one. The inner loop then runs through the positions in the vector, effecting a mini-insertion sort on the subsequences of the vector consisting of positions differing by multiples of the gap.

The internally defined insert! procedure differs from the one used in the insertion sort in that only positions separated by some multiple of the specified gap are considered; otherwise the algorithm is identical.

(define shell-sort!
  (lambda (v . opt)

    (let ((precedes? (if (null? opt) < (car opt)))
          (len (vector-length v)))

      (let ((insert!
             (lambda (position gap)
               (let ((new (vector-ref v position)))
                 (let loop ((old-trial position)
                            (trial (- position gap)))
                   (if (negative? trial)    ; at the left end: stop!
                       (vector-set! v old-trial new)
                       (let ((displaced (vector-ref v trial)))
                         (if (precedes? new displaced)
                           (begin
                             (vector-set! v old-trial displaced)
                             (loop trial (- trial gap)))
                           (vector-set! v old-trial new)))))))))

        (do ((gap (gap-size-not-exceeding len) (quotient gap 3))) 
            ((zero? gap))
          (do ((position gap (+ position 1)))
              ((<= len position))
            (insert! position gap)))))))
The computation of the initial gap size is performed by this auxiliary procedure:
(define gap-size-not-exceeding
  (lambda (n)
    (let loop ((old 1)
               (new 4))
      (if (< n new)
          old
          (loop new (+ (* 3 new) 1))))))


This document is available on the World Wide Web as

http://www.math.grin.edu/~stone/events/scheme-workshop/shellsort.html


created July 16, 1995
last revised June 25, 1996

John David Stone (stone@math.grin.edu)