View
217
Download
0
Category
Tags:
Preview:
Citation preview
David Evanshttp://www.cs.virginia.edu/evans
Class 20: Quick Sorting
CS200: Computer ScienceUniversity of VirginiaComputer Science
Queen’s University, Belfast, Northern Ireland
3 March 2004 CS 200 Spring 2004 2
TuttleSort(define (TuttleSort cf lst) (if (null? lst) lst (let ((most (find-most cf lst))) (cons most (TuttleSort cf (delete lst most))))))
(define (find-most cf lst) (insertl (lambda (c1 c2) (if (cf c1 c2) c1 c2)) lst (car lst)))
TuttleSort is (n2)If we double the length of the list, we
amount of work sort does approximately quadruples.
3 March 2004 CS 200 Spring 2004 3
Insert Sort(define (insertsort cf lst) (if (null? lst) null (insertel cf
(car lst) (insertsort cf
(cdr lst)))))
(define (insertel cf el lst) (if (null? lst) (list el) (if (cf el (car lst))
(cons el lst) (cons (car lst) (insertel cf el
(cdr lst))))))
insertsort is (n2)
3 March 2004 CS 200 Spring 2004 4
Divide and Conquer• Both TuttleSort and InsertSort divide the
problem of sorting a list of length n into:– Sorting a list of length n-1
– Doing the right thing with one element
• Hence, there are always n steps– And since each step is (n), they are (n2)
• To sort more efficiently, we need to divide the problem more evenly each step
3 March 2004 CS 200 Spring 2004 5
Can we do better?
(insertel < 88 (list 1 2 3 5 6 23 63 77 89 90))
Suppose we had procedures(first-half lst)(second-half lst)
that quickly divided the list in two halves?
3 March 2004 CS 200 Spring 2004 6
Insert Halves
(define (insertelh cf el lst) (if (null? lst) (list el) (let ((fh (first-half lst)) (sh (second-half lst))) (if (cf el (car fh)) (append (cons el fh) sh) (if (null? sh) (append fh (list el)) (if (cf el (car sh)) (append (insertelh cf el fh) sh) (append fh (insertelh cf el sh))))))))
3 March 2004 CS 200 Spring 2004 7
Evaluating insertelh> (insertelh < 3 (list 1 2 4 5 7))|(insertelh #<procedure:traced-<> 3 (1 2 4 5 7))| (< 3 1)| #f| (< 3 5)| #t| (insertelh #<procedure:traced-<> 3 (1 2 4))| |(< 3 1)| |#f| |(< 3 4)| |#t| |(insertelh #<procedure:traced-<> 3 (1 2))| | (< 3 1)| | #f| | (< 3 2)| | #f| | (insertelh #<procedure:traced-<> 3 (2))| | |(< 3 2)| | |#f| | (2 3)| |(1 2 3)| (1 2 3 4)|(1 2 3 4 5 7)(1 2 3 4 5 7)
(define (insertelh cf el lst) (if (null? lst) (list el) (let ((fh (first-half lst)) (sh (second-half lst))) (if (cf el (car fh)) (append (cons el fh) sh) (if (null? sh) (append fh (list el)) (if (cf el (car sh)) (append (insertelh cf el fh) sh) (append fh (insertelh cf el sh))))))))
Every time we call insertelh, the sizeof the list is approximately halved!
3 March 2004 CS 200 Spring 2004 8
How much work is insertelh?
Suppose first-half and second-half are (1) (define (insertelh cf el lst)
(if (null? lst) (list el) (let ((fh (first-half lst)) (sh (second-half lst))) (if (cf el (car fh)) (append (cons el fh) sh) (if (null? sh) (append fh (list el)) (if (cf el (car sh)) (append (insertelh cf el fh) sh) (append fh
(insertelh cf el sh))))))))
Each time we callinsertelh, the size oflst halves. So, doublingthe size of the list only increases the number ofcalls by 1.
List Size Number of insertelh applications1 12 24 38 416 5
3 March 2004 CS 200 Spring 2004 9
How much work is insertelh?
Suppose first-half and second-half are (1)Each time we call
insertelh, the size oflst halves. So, doublingthe size of the list only increases the number ofcalls by 1.
List Size Number of insertelh applications1 12 24 38 416 5
insertelh is (log2 n)
log2 a = bmeans2b = a
3 March 2004 CS 200 Spring 2004 10
insertsorth
(define (insertsorth cf lst) (if (null? lst) null (insertelh cf
(car lst) (insertsorth
cf (cdr lst)))))insertsorth would be (n log2 n)if we have fast first-half/second-half
Same as insertsort, except uses insertelh(define (insertelh cf el lst) (if (null? lst) (list el) (let ((fh (first-half lst)) (sh (second-half lst))) (if (cf el (car fh)) (append (cons el fh) sh) (if (null? sh) (append fh (list el)) (if (cf el (car sh)) (append (insertelh cf el fh) sh) (append fh
(insertelh cf el sh))))))))
3 March 2004 CS 200 Spring 2004 11
Is there a fast first-half procedure?
• No!
• To produce the first half of a list length n, we need to cdr down the first n/2 elements
• So:– first-half is (n) – insertelh calls first-half every time…so
– insertelh is (n) * (log2 n) = (n log2 n)
– insertsorth is (n) * (n log2 n) = (n2 log2 n)Yikes! We’ve done all this work, and its still worse than our simple TuttleSort!
3 March 2004 CS 200 Spring 2004 12
3 March 2004 CS 200 Spring 2004 13
The Great Lambda Treeof Ultimate Knowledgeand Infinite Power
3 March 2004 CS 200 Spring 2004 14
Sorted Binary Trees
el
A tree containingall elements x suchthat (cf x el) is true
A tree containingall elements x suchthat (cf x el) is false
left right
3 March 2004 CS 200 Spring 2004 15
Tree Example
5
2 8
741
3 cf: <
null null
3 March 2004 CS 200 Spring 2004 16
Representing Trees
(define (make-tree left el right) (list left el right))
(define (get-left tree) (first tree))
(define (get-element tree) (second tree))
(define (get-right tree) (third tree))
left and right are trees(null is a tree)
tree must be a non-null tree
tree must be a non-null tree
tree must be a non-null tree
3 March 2004 CS 200 Spring 2004 17
Trees as Lists
52 8
1 (make-tree (make-tree (make-tree null 1 null) 2 null) 5 (make-tree null 8 null))
(define (make-tree left el right) (list left el right))
(define (get-left tree) (first tree))(define (get-element tree) (second tree))(define (get-right tree) (third tree))
3 March 2004 CS 200 Spring 2004 18
insertel-tree(define (insertel-tree cf el tree) (if (null? tree) (make-tree null el null) (if (cf el (get-element tree)) (make-tree (insertel-tree cf el (get-left tree)) (get-element tree) (get-right tree)) (make-tree (get-left tree) (get-element tree) (insertel-tree cf el (get-right tree))))))
If the tree is null, make a new tree with el as its element and no left orright trees.
Otherwise, decideif el should be in the left or right subtree.insert it into thatsubtree, but leave theother subtree unchanged.
3 March 2004 CS 200 Spring 2004 19
How much work is insertel-tree?
(define (insertel-tree cf el tree) (if (null? tree) (make-tree null el null) (if (cf el (get-element tree)) (make-tree (insertel-tree cf el (get-left tree)) (get-element tree) (get-right tree)) (make-tree (get-left tree) (get-element tree) (insertel-tree cf el (get-right tree))))))
Each time we callinsertel-tree, the size ofthe tree. So, doublingthe size of the tree only increases the number ofcalls by 1!
insertel-tree is (log2 n)
log2 a = bmeans 2b = a
3 March 2004 CS 200 Spring 2004 20
insertsort-tree
(define (insertsort-worker cf lst) (if (null? lst) null (insertel-tree cf (car lst) (insertsort-worker cf (cdr lst)))))
(define (insertsort cf lst) (if (null? lst) null (insertel cf (car lst)
(insertsort cf (cdr lst)))))
No change…but insertsort-worker evaluates to a tree not a list!
(((() 1 ()) 2 ()) 5 (() 8 ()))
3 March 2004 CS 200 Spring 2004 21
extract-elements
We need to make a list of all the tree elements, from left to right.
(define (extract-elements tree) (if (null? tree) null (append (extract-elements (get-left tree)) (cons (get-element tree) (extract-elements (get-right tree))))))
3 March 2004 CS 200 Spring 2004 22
How much work is insertsort-tree?
(define (insertsort-tree cf lst) (define (insertsort-worker cf lst) (if (null? lst) null (insertel-tree cf (car lst) (insertsort-worker cf (cdr lst))))) (extract-elements (insertsort-worker cf lst)))
(n log2 n)(n) applicationsof insertel-treeeach is (log n)
3 March 2004 CS 200 Spring 2004 23
0
2000
4000
6000
8000
10000
120002
10
18
26
34
42
50
58
66
74
82
90
98
n log2 ninsertsort-tree
n2 TuttleSort
Growth of time to sort random list
3 March 2004 CS 200 Spring 2004 24
Comparing sorts> (testgrowth tuttlesort)n = 250, time = 110n = 500, time = 371n = 1000, time = 2363n = 2000, time = 8162n = 4000, time = 31757(3.37 6.37 3.45 3.89)> (testgrowth insertsort)n = 250, time = 40n = 500, time = 180n = 1000, time = 571n = 2000, time = 2644n = 4000, time = 11537(4.5 3.17 4.63 4.36)
> (testgrowth insertsorth)n = 250, time = 251n = 500, time = 1262n = 1000, time = 4025n = 2000, time = 16454n = 4000, time = 66137(5.03 3.19 4.09 4.02)> (testgrowth insertsort-tree)n = 250, time = 30n = 500, time = 250n = 1000, time = 150n = 2000, time = 301n = 4000, time = 1001(8.3 0.6 2.0 3.3)
3 March 2004 CS 200 Spring 2004 25
Can we do better?
• Making all those trees is a lot of work
• Can we divide the problem in two halves, without making trees?
Continues in Lecture 21…
Recommended