CS61B, 2019
Lecture 16: ADTs and BSTs
Abstract Data Types
Interfaces vs. Implementation
In class:
In projects:
List61B
AList
SLList
Deque
Array
Deque
LinkedList
Deque
Interfaces vs. Implementation
With DisjointSets, we saw a much richer set of possible implementations.
DisjointSets
ListOfSetsDS
QuickFindDS
QuickUnionDS
WeightedQuickUnionDS
Abstract Data Types
An Abstract Data Type (ADT) is defined only by its operations, not by its implementation.
Deque ADT:
Deque
Array
Deque
LinkedList
Deque
ArrayDeque and LinkedList Deque are implementations of the Deque ADT.
Another example of an ADT: The Stack
The Stack ADT supports the following operations:
insertBack()
getBack()
get(int i)
deleteBack()
push(int x)
pop()
4
6
2
The Stack ADT: yellkey.com/?
The Stack ADT supports the following operations:
Which implementation do you think would result in faster overall performance?
insertBack()
getBack()
get(int i)
deleteBack()
push(int x)
pop()
4
The Stack ADT: yellkey.com/?
The Stack ADT supports the following operations:
Which implementation do you think would result in faster overall performance?
Both are about the same. No resizing for linked lists, so probably a lil faster.
insertBack()
getBack()
get(int i)
deleteBack()
push(int x)
pop()
4
The GrabBag ADT: yellkey.com/?
The GrabBag ADT supports the following operations:
Which implementation do you think would result in faster overall performance?
insertBack()
getBack()
get(int i)
deleteBack()
remove()
insert(int x)
sample()
size(int i)
The GrabBag ADT: yellkey.com/?
The GrabBag ADT supports the following operations:
Which implementation do you think would result in faster overall performance?
insertBack()
getBack()
get(int i)
deleteBack()
remove()
insert(int x)
sample()
size(int i)
Abstract Data Types in Java
One thing I particularly like about Java is the syntax differentiation between abstract data types and implementations.
Example: List<Integer> L = new ArrayList<>();
List
ArrayList
Linked
List
Collections
Among the most important interfaces in the java.util library are those that extend the Collection interface (btw interfaces can extend other interfaces).
Collection
List
Set
Map
Map Example
Maps are very handy tools for all sorts of tasks. Example: Counting words.
Map<String, Integer> m = new TreeMap<>();
String[] text = {"sumomo", "mo", "momo", "mo",
"momo", "no", "uchi"};
for (String s : text) {
int currentCount = m.getOrDefault(s, 0);
m.put(s, currentCount + 1);
}
m = {}
text = ["sumomo", "mo", "momo", "mo", \
"momo", "no", "uchi"]
for s in text:
current_count = m.get(s, 0)
m[s] = current_count + 1
Python equivalent
sumomo | 1 |
mo | 2 |
momo | 2 |
no | 1 |
uchi | 1 |
Java Libraries
The built-in java.util package provides a number of useful:
Today, we’ll learn the basic ideas behind the TreeSet and TreeMap.
Collection
List
Set
Map
ArrayList
Linked
List
TreeSet
HashSet
TreeMap
HashMap
Binary Search Trees
Analysis of an OrderedLinkedListSet<Character>
In an earlier lecture, we implemented a set based on unordered arrays. For the order linked list set implementation below, name an operation that takes worst case linear time, i.e. Θ(N).
size
contains
add
iterator
A
C
B
D
E
F
G
sent
7
size
Analysis of an OrderedLinkedListSet<Character>
In an earlier lecture, we implemented a set based on unordered arrays. For the order linked list set implementation below, name an operation that takes worst case linear time, i.e. Θ(N).
size
contains
add
iterator
A
C
B
D
E
F
G
sent
7
size
Optimization: Extra Links
Fundamental Problem: Slow search, even though it’s in order.
A
C
B
D
E
F
G
Optimization: Change the Entry Point
Fundamental Problem: Slow search, even though it’s in order.
A
C
B
D
E
F
G
Optimization: Change the Entry Point, Flip Links
Fundamental Problem: Slow search, even though it’s in order.
A
C
B
D
E
F
G
Optimization: Change the Entry Point, Flip Links
Fundamental Problem: Slow search, even though it’s in order.
A
C
B
D
E
F
G
Optimization: Change Entry Point, Flip Links, Allow Big Jumps
Fundamental Problem: Slow search, even though it’s in order.
A
C
B
D
E
F
G
A
C
B
D
E
F
G
BST Definitions
Tree
A tree consists of:
Green structures below are trees. Pink ones are not.
Rooted Trees and Rooted Binary Trees
In a rooted tree, we call one node the root.
In a rooted binary tree, every node has either 0, 1, or 2 children (subtrees).
A
B
C
A
B
C
A
C
C
B
For each of these:
Not binary!
Binary Search Trees
A binary search tree is a rooted binary tree with the BST property.
BST Property. For every node X in the tree:
dog
bag
flat
alf
cat
elf
glut
debt
bus
ears
axe
cow
fish
gut
Binary Tree, but not a Binary Search Tree
Binary Search Tree
Binary Search Trees
Ordering must be complete, transitive, and antisymmetric. Given keys p and q:
One consequence of these rules: No duplicate keys allowed!
dog
bag
flat
alf
cat
elf
glut
debt
bus
ears
axe
cow
fish
gut
Binary Tree, but not a Binary Search Tree
Binary Search Tree
BST Operations: Search
Finding a searchKey in a BST (come back to this for the BST lab)
If searchKey equals T.key, return.
dog
bag
flat
alf
cat
elf
glut
Finding a searchKey in a BST
If searchKey equals T.key, return.
static BST find(BST T, Key sk) {
if (T == null)
return null;
if (sk.equals(T.key))
return T;
else if (sk ≺ T.key)
return find(T.left, sk);
else
return find(T.right, sk);
}
dog
bag
flat
alf
cat
elf
glut
BST Search: http://yellkey.com/?
What is the runtime to complete a search on a “bushy” BST in the worst case, where N is the number of nodes.
“bushiness” is an intuitive concept that we haven’t defined.
BST Search
What is the runtime to complete a search on a “bushy” BST in the worst case, where N is the number of nodes.
�Height of the tree is ~log2(N)
BSTs
Bushy BSTs are extremely fast.
Much (perhaps most?) computation is dedicated towards finding things in response to queries.
BST Operations: Insert
Inserting a New Key into a BST
Search for key.
Example:
insert “eyes”
dog
bag
flat
alf
cat
elf
glut
Inserting a New Key into a BST
Search for key.
eyes
A common rookie bad habit to avoid:
static BST insert(BST T, Key ik) {
if (T == null)
return new BST(ik);
if (ik ≺ T.key)
T.left = insert(T.left, ik);
else if (ik ≻ T.key)
T.right = insert(T.right, ik);
return T;
}
if (T.left == null)
T.left = new BST(ik);
else if (T.right == null)
T.right = new BST(ik);
dog
bag
flat
alf
cat
elf
glut
ARMS LENGTH RECURSION!!!! No good.
BST Operations: Delete
Deleting from a BST
3 Cases:
eyes
dog
bag
flat
alf
cat
elf
glut
Case 1: Deleting from a BST: Key with no Children
Deletion key has no children (“glut”):
eyes
dog
bag
flat
alf
cat
elf
glut
Case 1: Deleting from a BST: Key with no Children
Deletion key has no children (“glut”):
eyes
dog
bag
flat
alf
cat
elf
glut
Case 2: Deleting from a BST: Key with one Child
Example: delete(“flat”):
Goal:
Thus: Move flat’s parent’s pointer to flat’s child.
eyes
dog
bag
flat
alf
cat
elf
Case 2: Deleting from a BST: Key with one Child
Example: delete(“flat”):
Goal:
Thus: Move flat’s parent’s pointer to flat’s child.
eyes
dog
bag
flat
alf
cat
elf
Hard Challenge
Delete k.
e
b
g
a
d
f
v
p
y
m
r
x
z
k
Hard Challenge
Delete k.
e
b
g
a
d
f
v
p
y
m
r
x
z
k
Case 3: Deleting from a BST: Deletion with two Children (Hibbard)
Example: delete(“dog”)
Goal:
�Would bag work?
eyes
dog
bag
flat
alf
cat
elf
glut
Case 3: Deleting from a BST: Deletion with two Children (Hibbard)
Example: delete(“dog”)
Goal:
�Choose either predecessor (“cat”) or successor (“elf”).
eyes
dog
bag
flat
alf
cat
elf
glut
Hard Challenge (Hopefully Now Easy)
Delete k.
e
b
g
a
d
f
v
p
y
m
r
x
z
k
Hard Challenge (Hopefully Now Easy)
Delete k. Two solutions: Either promote g or m to be in the root.
e
b
g
a
d
f
v
p
y
m
r
x
z
k
Hard Challenge (Hopefully Now Easy)
Two solutions: Either promote g or m to be in the root.
e
b
g
a
d
f
v
p
y
m
r
x
z
Sets vs. Maps, Summary
Sets vs. Maps
Can think of the BST below as representing a Set:
sumomo
momo
mo
no
uchi
sumomo |
mo |
momo |
no |
uchi |
Sets vs. Maps
Can think of the BST below as representing a Set:
But what if we wanted to represent a mapping of word counts?
sumomo
momo
mo
no
uchi
sumomo |
mo |
momo |
no |
uchi |
sumomo | 1 |
mo | 2 |
momo | 2 |
no | 1 |
uchi | 1 |
????
Sets vs. Maps
To represent maps, just have each BST node store key/value pairs.
Note: No efficient way to look up by value.
sumomo 1
momo 2
mo 2
no 2
uchi 1
sumomo | 1 |
mo | 2 |
momo | 2 |
no | 1 |
uchi | 1 |
Summary
Abstract data types (ADTs) are defined in terms of operations, not implementation.
Several useful ADTs: Disjoint Sets, Map, Set, List.
We’ve seen two ways to implement a Set (or Map): ArraySet and using a BST.
BST Implementations:
BST Implementation Tips
Tips for BST Lab
static BST insert(BST T, Key ik) {
if (T == null)
return new BST(ik);
if (ik ≺ T.label()))
T.left = insert(T.left, ik);
else if (ik ≻ T.label())
T.right = insert(T.right, ik);
return T;
}
Always set, even if nothing changes!
Avoid “arms length base cases”.
if (T.left == null)
T.left = new BST(ik);
else if (T.right == null)
T.right = new BST(ik);
Citations
Probably photoshopped binary tree: http://cs.au.dk/~danvy/binaries.html