Lecture 15
Binary Search Trees - Special Trees
Logistics
This Week
For some, Ethics Module 5 - Identity
All grades prior to Quiz 1 are locked in. All grades between Q1 and Q2 will lock-in the moment Q2 begins. Any discrepancies, need to be taken care of prior to Q2.
Next Week
For some, Ethics Module 6 - Impact
Quiz 2 - 10/29 - Wednesday
Topics Overview for Q2
Binary Trees
Binary Trees
(define-struct binary-tree (data left right))
; A binary tree is...
; - an empty list or
; - (make-binary-tree any binary-tree binary-tree)
Pre-Recorded Lecture
Binary Trees
(define-struct binary-tree (data left right))
; A binary tree is...
; - an empty list or
; - (make-binary-tree any binary-tree binary-tree)
(define-struct branch (data left right))
; A binary tree is...
; - a number or
; - (make-branch number binary-tree binary-tree)
Pre-Recorded Lecture
Tutorial
Binary Trees
(define-struct binary-tree (data left right))
; A binary tree is...
; - an empty list or
; - (make-binary-tree any binary-tree binary-tree)
(define-struct branch (data left right))
; A binary tree is...
; - a number or
; - (make-branch number binary-tree binary-tree)
(define-struct human (name parentA parentB))
; An ancestry-tree is either
; - an empty list or
; - (make-human string ancestry-tree ancestry-tree)
Pre-Recorded Lecture
Tutorial
Exercise
Tree Recursion
(define (func args …) � (if easy-case?� solve-easy-case� (combine (func one-part)� (func other-part)))))
Binary Search Tree
An Example
Why is this a binary search tree?
An Example
Bigger Example
Bigger Example
This is the root. It has left and right sub-trees.
Bigger Example
This is the root. It has left and right sub-trees.
Right sub-tree has value greater than parent.
Bigger Example
This is the root. It has left and right sub-trees.
Right sub-tree has value greater than parent.
Left sub-tree has value less than parent.
Bigger Example
This is the root. It has left and right sub-trees.
Right sub-tree has value greater than parent.
Left sub-tree has value less than parent.
This value can be greater than 7 and 9…but can't be greater than 12!
Bigger Example
This is the root. It has left and right sub-trees.
Right sub-tree has value greater than parent.
Left sub-tree has value less than parent.
This value can be greater than 7 and 9…but can't be greater than 12!
This one can't be 8, 9, or 10 because then it would be greater than 7!
Wait…why would this matter?
Why do we care about keeping our data structured?
Why not just smoosh it all together?
Who cares what order it's in.
This is bogus.
Just put it in a list.
Why are we talking about this on a friday of all days.
You're Running the Tech Stack for HR at Walmart
Some Simplifications
Using struct to create an employee
; an employee is…
; - (make-employee number string)
(define-struct employee (ssn name))
Remember, this gives us:
; constructor: …
; predicate: …
; accessors/selectors: …, …
Woo. Step 1 is done!
(make-employee 1 "ava")
(make-employee 2 "george")
(make-employee 3 "jessica")
(make-employee 4 "steve")
Now how do we store a bunch of these things…
Version 1 - Inductive Data Definition
An employee database is simply a list of people.
In other words, a database is either:
Adding a person to the database
An employee database is simply a list of people.
In other words, a database is either:
Write a function (add employee database) that returns a database with that employee added to the database.
Adding a person to the database
(define (add employee db)
…)
(define ava-e (make-employee 1 "ava"))
(define jessica-e (make-employee 3 "jessica"))
(check-expect (add ava-e '()) (list ava-e))
(check-expect (add ava-e (list jessica-e)) (list ava-e jessica-e))
Adding a person to the database
(define (add employee db)
(cons employee db))
(define ava-e (make-employee 1 "ava"))
(define jessica-e (make-employee 3 "jessica"))
(check-expect (add ava-e '()) (list ava-e))
(check-expect (add ava-e (list jessica-e)) (list ava-e jessica-e))
Looking up a person to the database
; lookup-v1: number database -> employee or false
; find the person in the database via their ssn
; false if not found
Looking up a person to the database
; lookup-v1: number database -> employee or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v1 n db)
...)
(define test-db (list jessica-e ava-e george-e steve-e))
(check-expect (lookup-v1 2 test-db)
george-e)
(check-expect (lookup-v1 2 empty)
false)
(check-expect (lookup-v1 5 test-db)
false)
Looking up a person to the database
; lookup-v1: number database -> employee or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v1 n db)
(cond [(empty? db) false]
[(= n (employee-ssn (first db))) (first db)]
[else (lookup-v1 n (rest db))]))
Visualization of Mushroom Kingdom
Looking up a person to the database
; lookup-v1: number database -> employee or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v1 n db)
(cond [(empty? db) false]
[(= n (employee-ssn (first db))) (first db)]
[else (lookup-v1 n (rest db))]))
If we had 100 employees:
Can we do better?
What if we kept this whole list sorted by ssn…
Version 2
An employee database is a sorted list of people.
In other words, a database is either:
Version 2 - Inductive Data Definition
An employee database is a sorted list of people.
A database is either:
And has the invariant: each ssn number in l is larger than the ssn of employee e
Looking up a person to the database
; lookup-v2: number database -> employee or false
; find the person in the database via their ssn
; false if not found
Visualization of Mushroom Kingdom
Looking up a person to the database
; lookup-v2: number database -> employee or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v2 n db)
...)
(check-expect (lookup-v2 2 (list ava-e george-e jessica-e steve-e))
george-e)
(check-expect (lookup-v2 2 empty))
(check-expect (lookup-v2 5 (list ava-e george-e jessica-e steve-e))
false)
(check-expect (lookup-v2 1 (list george-p jessica-p steve-p))
false)
Looking up a person to the database
(define (lookup-v2 n db)
(cond [(empty? db) false]
[(< n (employee-ssn (first db))) false]
[(= n (employee-ssn (first db))) (first db)]
[else (lookup-v2 n (rest db))]))
Looking up a person to the database
(define (lookup-v2 n db)
(cond [(empty? db) false]
[(< n (employee-ssn (first db))) false]
[(= n (employee-ssn (first db))) (first db)]
[else (lookup-v2 n (rest db))]))
If we have 100 employees…
Oh wait…WHAT. All that work and no benefit?!?!?
Can we do better?
What if we put this in that whole binary search tree thing you talked about a little while ago…
Version 3
An employee database is a sorted tree of people.
In other words, a database is either:
(define-struct db-node (employee left right))
Visualization of Mushroom Kingdom
Looking up a person to the database
; lookup-v3: number database -> person or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v3 n db)
; what do you do if the db is empty?
; what do you do if the person at the root (db-node-employee db)
; has the ssn that we're looking for?
; what do you do if the number we are looking for is less than
; the person's at the root?
; what do you do if the number we are looking for is greater than
; the person's at the root?
)
Mega Mushroom Kingdom
Looking up a person to the database
; lookup-v3: number database -> person or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v3 n db)
(cond [(empty? db) false]
[(= n (employee-ssn (db-node-employee db))) (db-node-employee db)]
[(< n (employee-ssn (db-node-employee db))) (lookup-v3 n (db-node-left db))]
[(> n (employee-ssn (db-node-employee db))) (lookup-v3 n (db-node-right db))]))
Looking up a person to the database
; lookup-v3: number database -> person or false
; find the person in the database via their ssn
; false if not found
(define (lookup-v3 n db)
(cond [(empty? db) false]
[(= n (employee-ssn (db-node-employee db))) (db-node-employee db)]
[(< n (employee-ssn (db-node-employee db))) (lookup-v3 n (db-node-left db))]
[(> n (employee-ssn (db-node-employee db))) (lookup-v3 n (db-node-right db))]))
Linear Search vs. Binary Search
Mathematical Notation | Class Name | When the input doubles... |
| Constant | Runtime is unchanged ( ... x 1 ) |
| Logarithmic | Runtime increases by a constant |
| Linear | Runtime is doubled ( ... x 2 ) |
| Quasilinear | Runtime is approximately doubled |
| Quadratic | Runtime is quadrupled ( ... x 4 ) |
| Cubic | Runtime is octupled ( ... x 8 ) |
| Exponential | Runtime gets...really big |
Common Big O Classes
Mathematical Notation | Class Name | When the input doubles... |
| Constant | Runtime is unchanged ( ... x 1 ) |
| Logarithmic | Runtime increases by a constant |
| Linear | Runtime is doubled ( ... x 2 ) |
| Quasilinear | Runtime is approximately doubled |
| Quadratic | Runtime is quadrupled ( ... x 4 ) |
| Cubic | Runtime is octupled ( ... x 8 ) |
| Exponential | Runtime gets...really big |
Common Big O Classes
Linear Search
Mathematical Notation | Class Name | When the input doubles... |
| Constant | Runtime is unchanged ( ... x 1 ) |
| Logarithmic | Runtime increases by a constant |
| Linear | Runtime is doubled ( ... x 2 ) |
| Quasilinear | Runtime is approximately doubled |
| Quadratic | Runtime is quadrupled ( ... x 4 ) |
| Cubic | Runtime is octupled ( ... x 8 ) |
| Exponential | Runtime gets...really big |
Common Big O Classes
Binary Search