Search a binary tree stored in recursive cache oblivious layout to reduce memory transfers.
Van Emde Boas layout search stores a binary search tree in recursive memory order. The layout is cache oblivious, which means it does not need to know the cache line size or memory block size in advance.
The main idea is to split the tree into a top subtree and several bottom subtrees, then store each part recursively. Nodes that are close in the search path tend to be close in memory, which reduces cache misses across several levels of the memory hierarchy.
Problem
Given a binary search tree stored in van Emde Boas layout and a target value , find a node containing , or report failure.
Idea
A usual pointer based tree may scatter nodes across memory. A sorted array gives compact storage, but ordinary binary search can jump far through memory. Van Emde Boas layout arranges the tree recursively so that each subtree occupies a contiguous region.
The search operation is logically the same as binary search tree search:
if x < key:
go left
else:
go rightThe improvement comes from the layout, not from a new comparison rule.
Layout
For a complete binary tree of height :
- Split it near the middle height.
- Store the top subtree recursively.
- Store each bottom subtree recursively, from left to right.
This recursively clusters nodes by subtree.
For example, a height tree can be viewed as:
8
/ \
4 12
/ \ / \
2 6 10 14A recursive layout stores the root level and nearby subtree roots close together, then stores lower subtrees in compact blocks.
Algorithm
The search follows child links or computed child positions stored with the layout.
veb_layout_search(T, x):
u = root(T)
while u != null:
if key(u) == x:
return u
if x < key(u):
u = left_child(u)
else:
u = right_child(u)
return nullIf the layout uses an array rather than pointers, each node stores or derives the array positions of its children.
Example
Search for:
in the tree:
8
/ \
4 12
/ \ / \
2 6 10 14The logical search path is:
| step | node | comparison | action |
|---|---|---|---|
| 1 | 8 | 10 > 8 | go right |
| 2 | 12 | 10 < 12 | go left |
| 3 | 10 | equal | found |
The path is the same as ordinary binary search tree search. The storage order improves memory behavior.
Correctness
Van Emde Boas layout does not change the ordering invariant of the tree. For every node, all keys in the left subtree are smaller, and all keys in the right subtree are larger.
At each step, the comparison with the current key discards exactly one impossible subtree. Therefore the algorithm reaches the target if it exists, and reaches a null child if it does not.
Complexity
For a balanced tree with nodes:
| measure | cost |
|---|---|
| comparisons | |
| memory transfers | in the cache oblivious model |
| extra search space |
Here is the memory block size. The layout itself uses storage.
When to Use
Use van Emde Boas layout search when:
- the search tree is static or mostly static
- many searches run over the same data
- memory hierarchy costs dominate arithmetic costs
- cache size and block size should not be hard coded
- portability across machines matters
It is useful in search trees, static indexes, computational geometry structures, and memory sensitive lookup tables.
Implementation
A full van Emde Boas layout builder is more involved than the search procedure. This minimal version shows the search side using explicit child indexes.
class Node:
def __init__(self, key, left=-1, right=-1):
self.key = key
self.left = left
self.right = right
def veb_layout_search(nodes, root, x):
u = root
while u != -1:
node = nodes[u]
if node.key == x:
return u
if x < node.key:
u = node.left
else:
u = node.right
return -1type VEBNode struct {
Key int
Left int
Right int
}
func VEBLayoutSearch(nodes []VEBNode, root int, x int) int {
u := root
for u != -1 {
node := nodes[u]
if node.Key == x {
return u
}
if x < node.Key {
u = node.Left
} else {
u = node.Right
}
}
return -1
}