61B part 5.1 BSTs, B trees, red black trees
prev:[[start gitlet]]
next:[[61B-part5-2-hashing]]
disjoint sets: see [[Algs1.5_UnionFind]]
Abstract Data Types
it is defined only by its operations, not by its implementation.
for example: stack is defined by its operation: push(int x) and int pop(), not by its implementation (Array or LinkedList)
Collections
One of the most important interfaces in Java.
Maps, Lists, Sets are inherianted from it.
Maps
example:
1 | Map<String, Integer> m = new TreeMap<>(); |
the contents:
| sumomo | 1 |
|---|---|
| mo | 2 |
| momo | 2 |
| no | 1 |
| uchi | 1 |
| Basic ideas behind the TreeMaps and TreeSets: BST (Binary Search Tree) |
BSTs (Binary Search Trees)
The search in single linked list is very slow in Java.
![[LinkedList.png]]
To optimize it:
- Skip list (won’t be discussed): Add (random) express lanes
![[SkipList.png]] - Move pointer to middle and flip left links. It is faster!
![[BST0.png]]
How to make it even faster? – think of the recursion!
![[BST1.png]]
just do the middle search recursively, and then get the result.
definitions
Tree
consists of:
- A set of nodes.
- A set of edges that connect those nodes.
- Constraint: There is exactly one path between any two nodes.
Binary tree
a tree that a parent have 0/1/2 kids
BST
Ordering must be complete, transitive, and antisymmetric. Given keys p and q:
- Exactly one of p ≺ q and q ≺ p are true.
- p ≺ q and q ≺ r imply p ≺ r.
Operations
Finding
If searchKey equals T.key, return.
- If searchKey ≺ T.key, search T.left.
- If searchKey ≻ T.key, search T.right.
1
2
3
4
5
6
7
8
9
10static 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);
}
Insert
- find: do nothing
- didn’t find: create the key with appropriate link.
- Never implement like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// right code
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;
}
//wrong code
static BST insert(BST T, Key ik) {
if (T.left == null)
T.left = new BST(ik);
else if (T.right == null)
T.right = new BST(ik);
}
Delete
Just remember the ultimate goal: maintain BST ability!
B Trees (Balanced search trees)
Some basic terms in trees:
- depth: the number of links between a node and the root.
- height: the lowest depth of a tree.
- average depth: average of the total depths in the tree. You calculate this by taking $$∑𝑖=0𝐷𝑑𝑖𝑛𝑖𝑁N∑i=0Ddini$$ where di is depth and ni is number of nodes at that depth.
The worst case of BSTs are O(N). (exactly the same case as linked lists!)
(In most case, the complexity of a algorithm is represented by its worst one.)
However, it have been proven that when inserting data randomly, the tree are intended to be grow to the better case (~O(logN)).
But in real world, the data didn’t come in a time usually. They always comes in different times.
Avoiding imbalance
So, a crazy idea is that we never add leaves on our bottom!
![B- tree] (oi-wiki.org/ds/images/b-tree-1.svg) The Problem: if you end with the idea, multiple linked lists will come again!
Solution: set limit to the leaves, and move the elements onto their parents when the limit is reached.
 (princeton.edu)](https://algs4.cs.princeton.edu/33balanced/images/23tree-insert3b.png))
 (princeton.edu)](https://algs4.cs.princeton.edu/33balanced/images/23tree-split.png))
But, what if it is no longer a BST when the number have been moved?
split it into left and right part!
If anyone is longer than the certain limit, the number in the middle left or the center will be push up!
we can see that through the operation, the tree have reached perfect balance.
B Trees of L=3 is also called “2-3-4 trees”
To simulate the B Trees, you can look at this website
We can garantee that our trees are bushy!
Overall height: $$log_(L+1)N-log_2N$$
So, the complexity: logN
Red-black Trees
Rotation
disadvantage of the B trees: it is complex to implement
1 | public void put(Key key, Value val) { |
tree rotation
![[Tree_rotation.png]]rotateLeft(G): let x be the right child of G, and make G the new left child of x.
![[Pasted image 20240421103400.png]]
required: Self-balance!
Rotation can balance the tree while preserving tree property.
its code implementation needs one of the nodes are temparily stored.
AVL trees (not required)
平衡因子=右子树高度-左子树高度
if (|平衡因子|>1) rotation!
insert & delete are similar to BSTs.
演示
Red-black trees
how to represent a 2-3 tree as a BST? – rotate!
one possible way: conecting node
but sides are wasted!
![[Pasted image 20240421104317.png]]
another way: to use a “connected edge”
For convenience, the connected edge are signed as red, and others are black.
In code implementation, we can represent the color of edge in the child node.
![[Pasted image 20240421104718.png]]
using the left connected edge as the 2-3 trees are LLRB(left leaning red black tree).
search operations are the same as BSTs!
properties
- 和2-3树一一对应!(if the corresponding 2-3 trees are illegal, the LLRB is illegal)
- no node have 2 red links.
- every path from root to a leaf have the same number of black links.
- complexity: O(logN) (if maximum height of the corresponding 2-3 tree is H, the one of LLRB is 2H+1)
construction
first construct a 2-3 tree, and then modify it into LLRB🤣
- first put in like BST.
- using
Rotationto ensure the corresponding relationship (maintaining balance).
detailed construction rules:
- always use red side when inserting.
- insert it into the right side:
LeftRotation - produces adjacent red edges after inserting:
RightRotation - 2 red edges in one node:
flip
implementation
1 | private Node put(Node h, Key key, Value val) { |
