; Quicksort using Dr. Scheme ; Basic Quicksort algorithm as a recursive function ; Uses a filter function to implement partition. Filter ; is usually pre-defined in Scheme, but I write it her ; explicitly so that you can see how it works. (define filter (lambda (f ls) (foldl (lambda (e r) (if (f e) (append r (list e)) r)) '() ls))) ; Example usage of filter ;;(filter even? '(1 2 3 4 5 6)) ;;(filter odd? '(99 1 7 9 2 22 3 1 0)) ;;(filter (lambda (e) (number? e)) ;; '(1 "this is a string" '(a list) 4)) ;;(filter (lambda (e) (< e 0)) ;; '(-9 0 2 -2 6 4 -3 -99 201 16 -12)) ; A partition function that uses filter to partion a ; list based on a boolean operator and a pivot value. (define partition (lambda (op pivot ls) (filter (lambda (e) (op e pivot)) ls))) ; Example usage of partition ;;(partition <= 5 '(99 0 -1 9 -3 178 1024 2)) ;;(partition > 5 '(99 0 -1 9 -3 178 1024 2)) ; Now we can write quicksort. Note the use of let* (define quicksort (lambda (ls) (if (null? ls) '() (let* ((pivot (car ls)) (rest (cdr ls)) (left (partition < pivot rest)) (right (partition >= pivot rest))) (append (quicksort left) (list pivot) (quicksort right)))))) (define qsort quicksort) ;;(qsort '()) ;;(qsort '(0)) ;;(qsort '(1 2 3 4 5)) ;;(qsort '(5 4 3 2 1)) ;;(qsort '(0 -1 1 -2 2 -3 3 -4 4 -5 5)) ;;(qsort '(-99 0 1024 202 -1 77 18 -34 2048 19 1 9 7 3 2 -3 191)) ; QUESTION: Can quicksort be written tail recursively? ; To be tail recursive, we have to put all recursive calls to ; quicksort into "tail call position". A recursive function ; call is NOT in tail position if it is an operand to some ; function. In the case above, both recursive calls to quicksort ; are in operand positions of the append function. We could easily ; move one recursive call to tail position, but not both, so ; we would still have to maintain a return context, thereby ; canceling any chance at a tail call optimization. ; HOMEWORK: Modify the quicksort procedure so that it is possible ; to sort other ordered data types that have relational operators. ; For example, strings. Note that string comparison is done using ; the following predicates: (string? "Hello" "World") (string=? "A String" "A String")