Class 20: Quick Sorting Queen’s University, Belfast, Northern Ireland CS200: Computer Science University of Virginia Computer Science David Evans http://www.cs.virginia.edu/evans.

Download Report

Transcript Class 20: Quick Sorting Queen’s University, Belfast, Northern Ireland CS200: Computer Science University of Virginia Computer Science David Evans http://www.cs.virginia.edu/evans.

Class 20:
Quick
Sorting
Queen’s University, Belfast, Northern Ireland
CS200: Computer Science
University of Virginia
Computer Science
David Evans
http://www.cs.virginia.edu/evans
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
2
Insert Sort
(define (insertel cf el lst)
(define (insertsort cf lst)
(if (null? lst)
(if (null? lst)
(list el)
null
(if (cf el (car lst))
(insertel cf
(cons el lst)
(car lst)
(cons (car lst)
(insertsort cf
(insertel cf el
(cdr lst)))))
(cdr lst))))))
insertsort is (n2)
3 March 2004
CS 200 Spring 2004
3
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
4
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
5
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
6
Evaluating insertelh
> (insertelh < 3 (list 1 2 4 5 7))
(define (insertelh cf el lst)
|(insertelh #<procedure:traced-<> 3 (1 2 4 5 7))
(if (null? lst)
| (< 3 1)
(list el)
| #f
(let ((fh (first-half lst))
| (< 3 5)
| #t
(sh (second-half lst)))
| (insertelh #<procedure:traced-<> 3 (1 2 4))
(if (cf el (car fh))
| |(< 3 1)
(append (cons el fh) sh)
| |#f
(if (null? sh)
| |(< 3 4)
(append fh (list el))
| |#t
(if (cf el (car sh))
| |(insertelh #<procedure:traced-<> 3 (1 2))
(append (insertelh cf el fh) sh)
| | (< 3 1)
| | #f
(append fh (insertelh cf el sh))))))))
| | (< 3 2)
| | #f
| | (insertelh #<procedure:traced-<> 3 (2))
| | |(< 3 2)
| | |#f
| | (2 3)
Every time we call
, the size
| |(1 2 3)
of the list is approximately halved!
| (1 2 3 4)
|(1 2 3 4 5 7)
(1 2 3 4 5 7)
3 March 2004
CS 200 Spring 2004
7
insertelh
How much work is insertelh?
Suppose first-half and second-half are  (1)
Each time we call
insertelh, the size of
lst halves. So, doubling
the size of the list only
increases the number of
calls by 1.
List Size
1
2
4
8
16
3 March 2004
(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)
Number of insertelh applications
(append fh (list el))
1
(if (cf el (car sh))
2
(append (insertelh cf el fh) sh)
3
(append fh
4
(insertelh cf el sh))))))))
5
CS 200 Spring 2004
8
How much work is insertelh?
Suppose first-half and second-half are  (1)
Each time we call
insertelh, the size of
lst halves. So, doubling
the size of the list only
increases the number of
calls by 1.
List Size
1
2
4
8
16
3 March 2004
insertelh is  (log2 n)
Number of insertelh applications
1
2
3
4
5
CS 200 Spring 2004
log2 a = b
means
b
2 =a
9
insertsorth
Same as insertsort, except uses insertelh
(define (insertsorth cf lst)
(if (null? lst)
null
(insertelh cf
(car lst)
(insertsorth
cf
(cdr lst)))))
(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))))))))
insertsorth would be (n log2 n)
if we have fast first-half/second-half
3 March 2004
CS 200 Spring 2004
10
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
11
3 March 2004
CS 200 Spring 2004
12
The Great
Lambda
Tree
of Ultimate
Knowledge
and Infinite
Power
3 March 2004
CS 200 Spring 2004
13
Sorted Binary Trees
e
l
left
A tree containing
all elements x such
that (cf x el) is true
3 March 2004
right
A tree containing
all elements x such
that (cf x el) is false
CS 200 Spring 2004
14
Tree Example
3
cf: <
5
2
4
1
null
3 March 2004
8
7
null
CS 200 Spring 2004
15
Representing Trees
(define (make-tree left el right)
(list left el right))
left and right are trees
(null is a tree)
(define (get-left tree)
(first tree))
tree must be a non-null tree
(define (get-element tree)
(second tree))
tree must be a non-null tree
(define (get-right tree)
(third tree))
3 March 2004
CS 200 Spring 2004
tree must be a non-null tree
16
Trees as Lists
(define (make-tree left el right)
(list left el right))
5
2
1
(define (get-left tree)
(first tree))
(define (get-element tree)
(second tree))
(define (get-right tree)
(third tree))
8
(make-tree (make-tree (make-tree null 1 null)
2
null)
5
(make-tree null 8 null))
3 March 2004
CS 200 Spring 2004
17
insertel-tree
(define (insertel-tree cf el tree)
If the tree is null, make a new tree
(if (null? tree)
with el as its element and no left or
(make-tree null el null)
right trees.
(if (cf el (get-element tree))
(make-tree
(insertel-tree cf el (get-left tree)) Otherwise, decide
if el should be in
(get-element tree)
the left or right subtree.
(get-right tree))
insert it into that
subtree, but leave the
(make-tree
other subtree unchanged.
(get-left tree)
(get-element tree)
(insertel-tree cf el (get-right tree))))))
3 March 2004
CS 200 Spring 2004
18
How much work is insertel-tree?
Each time we call
(define (insertel-tree cf el tree)
insertel-tree, the size of
(if (null? tree)
the tree. So, doubling
(make-tree null el null)
(if (cf el (get-element tree))
the size of the tree only
(make-tree
increases the number of
(insertel-tree cf el (get-left tree))
calls by 1!
(get-element tree)
(get-right tree))
insertel-tree is
(make-tree
(get-left tree)
(log2 n)
(get-element tree)
(insertel-tree cf el (get-right tree))))))

log2 a = b
means 2b = a
3 March 2004
CS 200 Spring 2004
19
insertsort-tree
(define (insertsort cf lst)
(if (null? lst) null
(insertel cf (car lst)
(insertsort cf (cdr lst)))))
(define (insertsort-worker cf lst)
(if (null? lst) null
(insertel-tree cf (car lst)
(insertsort-worker 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
20
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
21
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) applications
of insertel-tree
each is (log n)
3 March 2004
(n log2 n)
CS 200 Spring 2004
22
Growth of time to sort random list
12000
n2
TuttleSort
10000
8000
6000
4000
2000
3 March 2004
CS 200 Spring 2004
98
90
82
74
66
58
50
42
34
26
18
10
2
0
n log2 n
insertsort-tree
23
Comparing sorts
> (testgrowth tuttlesort)
n = 250, time = 110
n = 500, time = 371
n = 1000, time = 2363
n = 2000, time = 8162
n = 4000, time = 31757
(3.37 6.37 3.45 3.89)
> (testgrowth insertsort)
n = 250, time = 40
n = 500, time = 180
n = 1000, time = 571
n = 2000, time = 2644
n = 4000, time = 11537
(4.5 3.17 4.63 4.36)
3 March 2004
> (testgrowth insertsorth)
n = 250, time = 251
n = 500, time = 1262
n = 1000, time = 4025
n = 2000, time = 16454
n = 4000, time = 66137
(5.03 3.19 4.09 4.02)
> (testgrowth insertsort-tree)
n = 250, time = 30
n = 500, time = 250
n = 1000, time = 150
n = 2000, time = 301
n = 4000, time = 1001
(8.3 0.6 2.0 3.3)
CS 200 Spring 2004
24
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…
3 March 2004
CS 200 Spring 2004
25