Skip to content

Van Emde Boas Layout Search

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 xx, find a node containing xx, 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 right

The improvement comes from the layout, not from a new comparison rule.

Layout

For a complete binary tree of height hh:

  1. Split it near the middle height.
  2. Store the top subtree recursively.
  3. Store each bottom subtree recursively, from left to right.

This recursively clusters nodes by subtree.

For example, a height 33 tree can be viewed as:

          8
       /     \
      4       12
     / \     /  \
    2   6   10   14

A 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 null

If the layout uses an array rather than pointers, each node stores or derives the array positions of its children.

Example

Search for:

x=10 x = 10

in the tree:

          8
       /     \
      4       12
     / \     /  \
    2   6   10   14

The logical search path is:

stepnodecomparisonaction
1810 > 8go right
21210 < 12go left
310equalfound

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 nn nodes:

measurecost
comparisonsO(logn)O(\log n)
memory transfersO(logBn)O(\log_B n) in the cache oblivious model
extra search spaceO(1)O(1)

Here BB is the memory block size. The layout itself uses O(n)O(n) 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 -1
type 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
}