Insertion sort

Goals: This laboratory exercise explores the insertion sort algorithm and provides additional practice with do expressions.

Preparation: Reread section 10.2.1 of the textbook, which discusses the insertion sort in the context of both lists and vectors.

Insertion Sort With Lists: The text presents the following procedures as part of the discussion of the insertion sort for lists:


(define insertionsort
   (lambda (ls)
       (if (singleton-list? ls)
           ls
           (insert (car ls) (insertionsort (cdr ls)))
       )
   )
)

(define insert
   (lambda (a ls)
       (cond ((null? ls) (cons a '()))
             ((< a (car ls)) (cons a ls))
             (else (cons (car ls) (insert a (cdr ls))))
       )
   )
)

(define singleton-list?
   (lambda (ls)
       (and (pair? ls) (null? (cdr ls)))
   )
)
  1. To clarify what these procedures return, type in the following expressions and explain how each result is obtained.
    
    (insert 5 '(1 3 4 7 8))
    (insert 0 '(1 3 4 5 7 8))
    (insert 9 '(0 1 3 4 5 7 8))
    (insertionsort '(2 5 8 9 1 4 7))
    (insertionsort '(9 8 7 6 5 4 3 2 1))
    (insertionsort '(2 4 6 8 10))
    (insertionsort (string->list "test"))
    
  2. Write appropriate pre-conditions and post-conditions for insert and insertionsort.

  3. Write a procedure iter-insert which performs the same work as insert, but which uses an iterative do expression rather than recursion.

    Hints:
    Within a do-expression, focus first on what work needs to be done repeatedly. This can help identify what local variables to use, how to initialize them, and how to update them. Here, we will want to work down the list -- successively deleting elements of the remaining list and keeping track of the elements encountered so far.

    Next, consider when to stop. Here, we continue going down the list until the list is empty or until we find where to put the new element. Such a stopping condition can suggest the test for the do-expression.

    Finally, determine what result should be returned. This can guide you about what to write for the postlude. Here, we want to return a fully-constructed list.

  4. Write an iterative version of insertionsort on lists.

Insertion Sort With Vectors: The text discusses a similar approach for sorting elements of a vector. The following code provides an iterative version of the text's code for vector-insertionsort!, and translates the letrec in vector-insert! to a named let expression.

(define vector-insertsort!
   (lambda (v)
       (do ((size (vector-length v))   ; variables
            (k 1 (+ k 1)))
           ((>= k size))               ; condition
           (vector-insert! k v)        ; loop body
       )
   )
)

(define vector-insert!
   (lambda (k vec)
      (let ((val (vector-ref vec k)))
           (let insert-h ((m k))
               (if (zero? m)
                   (vector-set! vec 0 val)
                   (let ((comp (vector-ref vec (sub1 m))))
                       (if (< val comp)
                           (begin
                               (vector-set! vec m comp)
                               (insert-h (sub1 m))
                           )
                           (vector-set! vec m val)
                       )
                   )
               )
           )
       )
   )
)
In this definition of vector-insertsort!, note that variable size is initialized but not updated. Following the definition of the Scheme language for the do-expression, the above declaration

(size (vector-length v))

initializes the size variable, but size is not automatically changed from one iteration of the loop to the next. The Scheme language definition notes that this part of a do-expression is equivalent to

(size (vector-length v) size)

that is, size is replaced by itself in subsequent times through the loop.

  1. Check that vector-insertsort! works as expected by typing the following sequence:
    
    (define data  #(2 5 8 9 1 4 7))
    data
    (vector-insertsort! data)
    data
    
    In this test, why is it necessary to define data initially?

  2. How would you change one or both of these procedures, so sorting would work when each element of the vector was a character rather than a number?

  3. Review the iterative version of vector-insertsort! with the recursive version in the text. Write a few sentences to compare the two approaches.

  4. Insert the following lines immediately after the (lambda (k vec) line in vector-insert!. These lines allow us to follow each step in the vector insertion sort processing.
    
    (display k)
    (display "   ")
    (display vec)
    (newline)
    
    Now, use the same test steps (starting with (define data ...) above, and explain what processing is done from each output line to the next.

  5. Rewrite vector-insert! using an iterative do expression in place of the recursion.


This document is available on the World Wide Web as

http://www.math.grin.edu/courses/Scheme/lab-insertion-sort.html

created April 16, 1997
last revised May 28, 1997
Henry Walker (walker@math.grin.edu)