---
date: '2024-11-18'
description: space-optimized prefix trie where single-child nodes merge with parents, enabling o(k) lookup, insertion, and deletion operations.
id: Radix tree
modified: 2026-06-05 15:08:23 GMT-04:00
tags:
  - technical
title: Radix tree
created: '2024-11-18'
published: '2024-11-18'
pageLayout: default
slug: thoughts/Radix-tree
permalink: https://aarnphm.xyz/thoughts/Radix-tree.md
generator:
  quartz: v4.6.0
  hostedProvider: Cloudflare
  baseUrl: aarnphm.xyz
full: https://aarnphm.xyz/llms-full.txt
---
A prefix [[thoughts/university/twenty-three-twenty-four/sfwr-2c03/Hash tables|trie]] in which each node that is the only child is merged with its parent.

![[thoughts/images/Patricia_trie.svg]]

_By Claudio Rocchini - Own work, CC BY 2.5, [wikimedia](https://commons.wikimedia.org/w/index.php?curid=2118795)_

result: number of all internal nodes is at most the radix $r$ of the tree, where $r=2^{x} \forall x \in \mathbb{R}^d \cap x \ge 1$

Edge can be labelled with sequences of elements as well as single elements.

key at each node is compared chunk-of-bits, where quantity of bits in any given chunk is the radix $r$ of the radix tree:

- $r=2$ then radix trie is binary, which minimise sparsity at the expense of maximising trie-depth
- $r \ge 4$ is a power of two, then it is a r-ary trie, which lessen the depth at the expense of some sparseness

**Lookup pseudocode**:

<div class="ps-root" data-inline-macros=""><span type="button" class="clipboard-button ps-clipboard" aria-label="Copy pseudocode to clipboard"><svg width="16" height="16" viewBox="0 0 16 16" class="copy-icon"><use href="#github-copy"></use></svg><svg width="16" height="16" viewBox="0 0 16 16" class="check-icon"><use href="#github-check" fill-rule="evenodd" fill="rgb(63, 185, 80)"></use></svg></span><span class="ps-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><annotation encoding="application/x-tex">"\\begin{algorithm}\n\\caption{Lookup}\n\\begin{algorithmic}\n\\State $\\text{traverseNode} \\gets \\text{root}$\n\\State $\\text{elementsFound} \\gets 0$\n\\While{traverseNode $\\neq \\text{null} \\land \\neg \\text{traverseNode}.\\text{isLeaf}() \\land \\text{elementsFound} &#x3C; \\text{length}(x)$}\n    \\State nextEdge $\\gets$ select edge from traverseNode.edges where edge.label is a prefix of $x.\\text{suffix}(\\text{elementsFound})$\n    \\If{nextEdge $\\neq \\text{null}$}\n        \\State traverseNode $\\gets$ nextEdge.targetNode\n        \\State elementsFound $\\gets$ elementsFound + length(nextEdge.label)\n    \\Else\n        \\State traverseNode $\\gets$ null\n    \\EndIf\n\\EndWhile\n\\State \\Return traverseNode $\\neq \\text{null} \\land \\text{traverseNode}.\\text{isLeaf}() \\land \\text{elementsFound} = \\text{length}(x)$\n\\end{algorithmic}\n\\end{algorithm}"</annotation></semantics></math></span>
<div class="ps-algorithm with-caption">
<p class="ps-line" style="text-indent:-0.6em;padding-left:0.6em;">
<span class="ps-keyword">Algorithm 1 </span>Lookup</p>
<div class="ps-algorithmic with-linenum">
<div class="ps-block" style="margin-left:1.2em;">
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:0em;">1:</span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>traverseNode</mtext><mo>←</mo><mtext>root</mtext></mrow><annotation encoding="application/x-tex">\text{traverseNode} \gets \text{root}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">traverseNode</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6151em;"></span><span class="mord text"><span class="mord">root</span></span></span></span></span></p>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:0em;">2:</span><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mtext>elementsFound</mtext><mo>←</mo><mn>0</mn></mrow><annotation encoding="application/x-tex">\text{elementsFound} \gets 0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">elementsFound</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">←</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">0</span></span></span></span></p>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:0em;">3:</span><span class="ps-keyword">while </span>traverseNode <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo mathvariant="normal">≠</mo><mtext>null</mtext><mo>∧</mo><mi mathvariant="normal">¬</mi><mtext>traverseNode</mtext><mi mathvariant="normal">.</mi><mtext>isLeaf</mtext><mo stretchy="false">(</mo><mo stretchy="false">)</mo><mo>∧</mo><mtext>elementsFound</mtext><mo>&#x3C;</mo><mtext>length</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neq \text{null} \land \neg \text{traverseNode}.\text{isLeaf}() \land \text{elementsFound} &#x3C; \text{length}(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mspace nobreak"></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">null</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">¬</span><span class="mord text"><span class="mord">traverseNode</span></span><span class="mord">.</span><span class="mord text"><span class="mord">isLeaf</span></span><span class="mopen">(</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7335em;vertical-align:-0.0391em;"></span><span class="mord text"><span class="mord">elementsFound</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">&#x3C;</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">length</span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span><span class="ps-keyword"> do</span></p>
<div class="ps-block" style="margin-left:0.6em;">
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-0.75em;">4:</span>nextEdge <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>←</mo></mrow><annotation encoding="application/x-tex">\gets</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">←</span></span></span></span> select edge from traverseNode.edges where edge.label is a prefix of <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>x</mi><mi mathvariant="normal">.</mi><mtext>suffix</mtext><mo stretchy="false">(</mo><mtext>elementsFound</mtext><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">x.\text{suffix}(\text{elementsFound})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">x</span><span class="mord">.</span><span class="mord text"><span class="mord">suffix</span></span><span class="mopen">(</span><span class="mord text"><span class="mord">elementsFound</span></span><span class="mclose">)</span></span></span></span></p>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-0.75em;">5:</span><span class="ps-keyword">if </span>nextEdge <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo mathvariant="normal">≠</mo><mtext>null</mtext></mrow><annotation encoding="application/x-tex">\neq \text{null}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mspace nobreak"></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">null</span></span></span></span></span><span class="ps-keyword"> then</span></p>
<div class="ps-block" style="margin-left:0.6em;">
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-1.5em;">6:</span>traverseNode <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>←</mo></mrow><annotation encoding="application/x-tex">\gets</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">←</span></span></span></span> nextEdge.targetNode</p>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-1.5em;">7:</span>elementsFound <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>←</mo></mrow><annotation encoding="application/x-tex">\gets</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">←</span></span></span></span> elementsFound + length(nextEdge.label)</p>
</div>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-0.75em;">8:</span><span class="ps-keyword">else</span></p>
<div class="ps-block" style="margin-left:0.6em;">
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-1.5em;">9:</span>traverseNode <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>←</mo></mrow><annotation encoding="application/x-tex">\gets</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.3669em;"></span><span class="mrel">←</span></span></span></span> null</p>
</div>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:-0.75em;">10:</span><span class="ps-keyword">end if</span></p>
</div>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:0em;">11:</span><span class="ps-keyword">end while</span></p>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:0em;">12:</span></p>
<p class="ps-line ps-code">
<span class="ps-linenum" style="left:0em;">13:</span><span class="ps-keyword">return </span>traverseNode <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo mathvariant="normal">≠</mo><mtext>null</mtext><mo>∧</mo><mtext>traverseNode</mtext><mi mathvariant="normal">.</mi><mtext>isLeaf</mtext><mo stretchy="false">(</mo><mo stretchy="false">)</mo><mo>∧</mo><mtext>elementsFound</mtext><mo>=</mo><mtext>length</mtext><mo stretchy="false">(</mo><mi>x</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">\neq \text{null} \land \text{traverseNode}.\text{isLeaf}() \land \text{elementsFound} = \text{length}(x)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mspace nobreak"></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">null</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">traverseNode</span></span><span class="mord">.</span><span class="mord text"><span class="mord">isLeaf</span></span><span class="mopen">(</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∧</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">elementsFound</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord text"><span class="mord">length</span></span><span class="mopen">(</span><span class="mord mathnormal">x</span><span class="mclose">)</span></span></span></span></p>
</div>
</div>
</div>
</div>

## complexity

Permits lookup, deletion, insertion in $O(k)$ rather than $O(\log n)$

Normally $k \ge \log n$, but in a balanced tree every comparison is a string comparison requires $O(k)$ worse-case time. Whereas in a trie all comparison require constant times, but takes $m$ comparisons to look up a string length $m$

