Home

Tries


A trie:

Trie Example

Important features of tries:

Representation


Assuming alphabetic strings:

#define ALPHABET_SIZE 26

struct node {
  struct node *children[ALPHABET_SIZE];
  bool finish; // marks the end of a key
  Data data; // data associated with key
};

Trie Insertion


Process for insertion:

trieInsert(t, key, data):
  Input: trie t,
         key of length m and associated data
  Output: t with key and data inserted

  if t is empty:
    t = new node

  if m = 0:
    t->finish = true
    t->data = data
  else:
    first = key[0]
    rest = key[1..m - 1] // i.e., slice off first character from key
    t->children[first] = trieInsert(t->children[first], rest, data)

  return t

Search is similar to insertion:

trieSearch(t, key):
  Input: trie t,
         key of length m
  Output: true if key is in t, false otherwise

  if t is empty:
    return false
  else if m = 0:
    return t->finish = true
  else:
    first = key[0]
    rest = key[1..m - 1]
    return trieSearch(t->children[first], rest)

Trie Deletion


Process for deletion:

trieDelete(t, key):
  Input: trie t,
         key of length m
  Output: t with key deleted
  return doTrieDelete(t, key, true)

doTrieDelete(t, key, isRoot):
  Input: trie t,
         key of length m,
         boolean isRoot indicating if t is the root node
  Output: t with key deleted
  if t is empty:
    return t
  else if m = 0:
    t->finish = false
  else:
    first = key[0]
    rest = key[1..m - 1]
    t->children[first] = doTrieDelete(t->children[first], rest, false)

  if isRoot = false and t->finish = false and t has no child nodes:
    return NULL
  else:
    return t

Analysis


Analysis of standard trie:

Variants


Different representations exist to reduce memory usage at the cost of increased running time:

Linked list of children


Have each node store a linked list of its children instead of an array of ALPHABET_SIZE pointers

struct node {
  struct child *children;
  bool finish;
  Data data;
};

struct child {
  char c;
  struct node *node;
  struct child *next;
};
Trie Linked List Example

We can simplify this representation by merging each linked list node with its corresponding trie node This produces the left-child right-sibling binary tree representation

struct node {
  char c;
  struct node *children;
  struct node *sibling;
  bool finish;
  Data data;
};
Trie Linked List Example

Analysis:

Alphabet Reduction


Break each 8-bit character into two 4-bit nybbles

This reduces the branching factor, i.e., the number of pointers in each node

Trie Alphabet Reduction Example

Analysis:

Compressed Tries


In a compressed trie, each node contains ≥ 1 character

Obtained by merging non-branching chains of nodes

Specifically, non-finishing nodes with only one child are merged with their child