;;; File: ;;; insertion-sort.txt ;;; Author: ;;; Samuel A. Rebelsky ;;; Version: ;;; 1.0 of November 2006 ;;; Procedure: ;;; insert ;;; Parameters: ;;; new-value, a Scheme value ;;; sorted, a Vector ;;; may-precede?, a binary predicate ;;; Purpose: ;;; Insert new-value into the proper place in sorted. ;;; Produces: ;;; new-ls, a new list of real numbers ;;; Preconditions: ;;; may-precede? is transitive and reflexive. [Unverified] ;;; sorted is arranged in increasing order. That is, ;;; (may-precede? (list-ref sorted i) (list-ref sorted (+ i 1))) ;;; for all reasonable values of i. [Unverified] ;;; Postconditions: ;;; new-ls is arranged in increasing order. ;;; new-ls is a permutation of (cons new-value sorted). (define insert (lambda (new-value sorted may-precede?) (let kernel ((rest sorted) (bypassed null)) (cond ((null? rest) (reverse (cons new-value bypassed))) ((may-precede? new-value (car rest)) (append (reverse (cons new-value bypassed)) rest)) (else (kernel (cdr rest) (cons (car rest) bypassed))))))) ;;; Procedure: ;;; insertion-sort! ;;; Paramters: ;;; may-precede?, a binary predicate ;;; vec, a vector ;;; Purpose: ;;; Sorts the vector. ;;; Produces: ;;; [Nothing; sorts in place] ;;; Preconditions: ;;; vec is a vector. ;;; may-precede? can be applied to any two elements of vec. ;;; may-precede? is transitive. ;;; Postconditions: ;;; The final state of vec is a permutation of the original state. ;;; vec is sorted. That is, ;;; (may-precede? (vector-ref vec i) (vector-ref vec (+ i 1))) ;;; for all reasonable values of i. (define insertion-sort! (lambda (may-precede? vec) (let ((len (vector-length vec))) (let kernel ((boundary 1)) ; The index of the first unsorted value (if (< boundary len) ; If we have elements left to sort (begin (insert! (vector-ref vec boundary) vec boundary may-precede?) (kernel (+ boundary 1)))))))) ;;; Procedure: ;;; insert! ;;; Parameters: ;;; new-element, a value ;;; vec, a vector of values ;;; boundary, an index into the vector ;;; may-precede?, a binary predicate ;;; Purpose: ;;; Insert new-element into the portion of vec between 0 and ;;; boundary, inclusive. ;;; Produces: ;;; Nothing; called for side effects. ;;; Preconditions: ;;; 0 <= boundary < (vector-length vec) ;;; The elements in positions 0..boundary-1 of vec are sorted. ;;; That is, (may-precede? (vector-ref vec i) (vector-ref vec (+ i 1))) ;;; for all 0 < i < boundary-1. ;;; Postconditions: ;;; The elements in positions 0..boundary of vec are sorted. ;;; That is, (may-precede? (vector-ref vec i) (vector-ref vec (+ i 1))) ;;; for all 0 < i < boundary. ;;; The elements in positions 0..boundary of vec after insert! finishes ;;; are a permutation of new-element and the elements that were in ;;; positions 0..(boundary-1) before the procedure started. (define insert! (lambda (new-element vec boundary may-precede?) (let kernel ((pos boundary)) (cond ; If we've reached the left end of the vector, we've run out of ; elements to shift. Insert the new element. ((zero? pos) (vector-set! vec pos new-element)) ; If we've reached a point at which the element to the left ; is smaller, we insert the new element here. ((may-precede? (vector-ref vec (- pos 1)) new-element) (vector-set! vec pos new-element)) ; Otherwise, we shift the current element to the right and ; continue. (else (vector-set! vec pos (vector-ref vec (- pos 1))) (kernel (- pos 1))))))) (define sample (vector 2 5 7 10 (random 20) (random 20) (random 20) (random 20)))