<script>!function(){functiont(t){document.documentElement.setAttribute("data-theme",t)}vare=function(){try{returnnewURLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{returnlocalStorage.getItem("theme")}catch(t){}}();t(null!==e?e:"light")}(),function(){try{constc=newURLSearchParams(window.location.search).entries();for(var[t,e]ofc)if(t.startsWith("docusaurus-data-")){vara=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><divid="__docusaurus"><divrole="region"aria-label="Skip to main content"><aclass="skipToContent_fXgn"href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><navaria-label="Main"class="navbar navbar--fixed-top"><divclass="navbar__inner"><divclass="navbar__items"><buttonaria-label="Toggle navigation bar"aria-expanded="false"class="navbar__toggle clean-btn"type="button"><svgwidth="30"height="30"viewBox="0 0 30 30"aria-hidden="true"><pathstroke="currentColor"stroke-linecap="round"stroke-miterlimit="10"stroke-width="2"d="M4 7h22M4 15h22M4 23h22"></path></svg></button><aclass="navbar__brand"href="/"><bclass="navbar__title text--truncate">mf</b></a><divclass="navbar__item dropdown dropdown--hoverable"><ahref="#"aria-haspopup="true"aria-expanded="false"role="button"class="navbar__link">Additional FI MU materials</a><ulclass="dropdown__menu"><li><aaria-current="page"class="dropdown__link dropdown__link--active"href="/algorithms/">Algorithms</a></li><li><aclass="dropdown__link"href="/c/">C</a></li><li><aclass="dropdown__link"href="/cpp/">C++</a></li></ul></div><aclass="navbar__item navbar__link"href="/contributions/">Contributions</a><aclass="navbar__item navbar__link"href="/talks/">Talks</a></div><divclass="navbar__items navbar__items--right"><aclass="navbar__item navbar__link"href="/blog/">Blog</a><divclass="toggle_vylO colorModeToggle_DEke"><buttonclass="clean-btn toggleButton_gllP toggleButtonDisabled_aARS"type="button"disabled=""title="Switch between dark and light mode (currently light mode)"aria-label="Switch between dark and light mode (currently light mode)"aria-live="polite"><svgviewBox="0 0 24 24"width="24"height="24"class="lightToggleIcon_pyhR"><pathfill="currentColor"d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svgviewBox="0 0 24 24"width="24"height="24"class="darkToggleIcon_wfgR"><pathfill="currentColor"d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg></button></div><divclass="navbarSearchContainer_Bca1"><buttontype="button"class="DocSearch DocSearch-Button"aria-label="Search"><spanclass="DocSearch-Button-Container"><svgwidth="20"height="20"class="DocSearch-Search-Icon"viewBox="0 0 20 20"><pathd="M14.38614.386l4.08774.0877-4.0877-4.0877c-2.
issues to occur.</p>
<h2class="anchor anchorWithStickyNavbar_LWe7"id="introduction">Introduction<ahref="#introduction"class="hash-link"aria-label="Direct link to Introduction"title="Direct link to Introduction"></a></h2>
<p>Hash tables are very commonly used to represent sets or dictionaries. Even when
you look up solution to some problem that requires set or dictionary, it is more
than likely that you'll find something that references usage of the hash table.
You might think it's the only possible option<sup><ahref="#user-content-fn-1"id="user-content-fnref-1"data-footnote-ref="true"aria-describedby="footnote-label">1</a></sup>, or it's the best one<sup><ahref="#user-content-fn-2"id="user-content-fnref-2"data-footnote-ref="true"aria-describedby="footnote-label">2</a></sup>.</p>
<p>One of the reasons to prefer hash tables over any other representation is the
fact that they are <strong>supposed</strong> to be faster than the alternatives, but the
truth lies somewhere in between.</p>
<p>One of the other possible implementations of the set is a balanced tree. Majorly
occurring implementations rely on the <em>red-black tree</em>, but you may see also
others like an <em>AVL tree</em><sup><ahref="#user-content-fn-3"id="user-content-fnref-3"data-footnote-ref="true"aria-describedby="footnote-label">3</a></sup> or <em>B-tree</em><sup><ahref="#user-content-fn-4"id="user-content-fnref-4"data-footnote-ref="true"aria-describedby="footnote-label">4</a></sup>.</p>
<h2class="anchor anchorWithStickyNavbar_LWe7"id="hash-table-v-trees">Hash Table v. Trees<ahref="#hash-table-v-trees"class="hash-link"aria-label="Direct link to Hash Table v. Trees"title="Direct link to Hash Table v. Trees"></a></h2>
<p>The most interesting part are the differences between their implementations. Why
should you choose hash table, or why should you choose the tree implementation?
Let's compare the differences one by one.</p>
<h3class="anchor anchorWithStickyNavbar_LWe7"id="requirements">Requirements<ahref="#requirements"class="hash-link"aria-label="Direct link to Requirements"title="Direct link to Requirements"></a></h3>
<p>We will start with the fundamentals on which the underlying data structures
rely. We can also consider them as <em>requirements</em> that must be met to be able to
use the underlying data structure.</p>
<p>Hash table relies on the <em>hash function</em> that is supposed to distribute the keys
in such way that they're evenly spread across the slots where the keys (or
pairs, for dictionary) are stored, but at the same time they're somewhat unique,
so no clustering occurs.</p>
<p>Trees depend on the <em>ordering</em> of the elements. They maintain the elements in
a sorted fashion, so for any pair of the elements that are used as keys, you
need to be able to decide which one of them is <em>smaller or equal to</em> the other.</p>
<p>Hash function can be easily created by using the bits that <em>uniquely</em> identify
a unique element. On the other hand, ordering may not be as easy to define.</p>
<divclass="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 12 16"><pathfill-rule="evenodd"d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Example</div><divclass="admonitionContent_BuS1"><p>If you are familiar with complex numbers, they are a great example of a key that
does not have ordering (unless you go element-wise for the sake of storing them
in a tree; though the ordering <strong>is not</strong> defined on them).</p><p>Hashing them is much easier though, you can just “combine” the hashes of the
real and imaginary parts of the complex number to get a hash of the complex
number itself.</p></div></div>
<h3class="anchor anchorWithStickyNavbar_LWe7"id="underlying-data-structure">Underlying data structure<ahref="#underlying-data-structure"class="hash-link"aria-label="Direct link to Underlying data structure"title="Direct link to Underlying data structure"></a></h3>
<p>The most obvious difference is the <em>core</em> of the idea behind these data
structures. Hash tables rely on data being stored in one continuous piece of
memory (the array) where you can “guess” (by using the hash function) the
location of what you're looking for in a constant time and also access that
location in the, said, constant time<sup><ahref="#user-content-fn-5"id="user-content-fnref-5"data-footnote-ref="true"aria-describedby="footnote-label">5</a></sup>. In case the hash function is
<em>not good enough</em><sup><ahref="#user-content-fn-6"id="user-content-fnref-6"data-footnote-ref="true"aria-describedby="footnote-label">6</a></sup>, you need to go in <em>blind</em>, and if it comes to the worst,
<li>Wherever I look, it takes me about the same time</li>
</ul></div></div>
<p>Let's compare side by side:</p>
<table><thead><tr><thstyle="text-align:right">time complexity</th><thstyle="text-align:center">hash table</th><thstyle="text-align:center">tree</th></tr></thead><tbody><tr><tdstyle="text-align:right">expected</td><tdstyle="text-align:center">constant</td><tdstyle="text-align:center">depends on the height</td></tr><tr><tdstyle="text-align:right">worst-case</td><tdstyle="text-align:center">gotta check everything</td><tdstyle="text-align:center">depends on the height</td></tr></tbody></table>
<h2class="anchor anchorWithStickyNavbar_LWe7"id="major-factors-of-hash-tables">Major Factors of Hash Tables<ahref="#major-factors-of-hash-tables"class="hash-link"aria-label="Direct link to Major Factors of Hash Tables"title="Direct link to Major Factors of Hash Tables"></a></h2>
<p>Let's have a look at the major factors that affect the efficiency and
functioning of a hash table. We have already mentioned the hash function that
plays a crucial role, but there are also different ways how you can implement
a hash table, so we will have a look at those too.</p>
<h3class="anchor anchorWithStickyNavbar_LWe7"id="hash-functions">Hash functions<ahref="#hash-functions"class="hash-link"aria-label="Direct link to Hash functions"title="Direct link to Hash functions"></a></h3>
<divclass="theme-admonition theme-admonition-info admonition_xJq3 alert alert--info"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 14 16"><pathfill-rule="evenodd"d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"></path></svg></span>info</div><divclass="admonitionContent_BuS1"><p>We will start with a definition of hash function in a mathematical definition
and type signature in some known language:</p><spanclass="katex-display"><spanclass="katex"><spanclass="katex-mathml"><mathxmlns="http://www.w3.org/1998/Math/MathML"display="block"><semantics><mrow><mi>h</mi><mo>:</mo><mi>T</mi><mo>→</mo><mimathvariant="double-struck">N</mi></mrow><annotationencoding="application/x-tex"> h : T \rightarrow \mathbb{N}</annotation></semantics></math></span><spanclass="katex-html"aria-hidden="true"><spanclass="base"><spanclass="strut"style="height:0.6944em"></span><spanclass="mord mathnormal">h</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mrel">:</span><spanclass="mspace"style="margin-right:0.2778em"></span></span><spanclass="base"><spanclass="strut"style="height:0.6833em"></span><spanclass="mord mathnormal"style="margin-right:0.13889em">T</span><spanclass="mspace"style="margin-right:0.2778em"></span><spanclass="mrel">→</span><spanclass="mspace"style="margin-right:0.2778em"></span></span><spanclass="base"><spanclass="strut"style="height:0.6889em"></span><spanclass="mord mathbb">N</span></span></span></span></span><p>For a type signature we will just take the declaration from C++<sup><ahref="#user-content-fn-7"id="user-content-fnref-7"data-footnote-ref="true"aria-describedby="footnote-label">7</a></sup>:</p><divclass="language-cpp codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-cpp codeBlock_bY9V thin-scrollbar"style="color:#393A34;background-color:#f6f8fa"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#393A34"><spanclass="token plain">std</span><spanclass="token double-colon punctuation"style="color:#393A34">::</span><spanclass="token plain">size_t </span><spanclass="token keyword"style="color:#00009f">operator</span><spanclass="token punctuation"style="color:#393A34">(</span><spanclass="token punctuation"style="color:#393A34">)</span><spanclass="token punctuation"style="color:#393A34">(</span><spanclass="token keyword"style="color:#00009f">const</span><spanclass="token plain"> T</span><spanclass="token operator"style="color:#393A34">&</span><spanclass="token plain"> key</span><spanclass="token punctuation"style="color:#393A34">)</span><spanclass="token plain"></span><spanclass="token keyword"style="color:#00009f">const</span><spanclass="token punctuation"style="color:#393A34">;</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p>If you compare with the mathematical definition, it is very similar, except for
the fact that the memory is not unlimited, so the <em>natural number</em> turned into
an <em>unsigned integer type</em> (on majority of platforms it will be a 64-bit
unsigned integer).</p></div></div>
<p>As we have already touched above, hash function gives “a guess” where to look
for the key (either when doing a look up, or for insertion to guess a suitable
spot for the insertion).</p>
<p>Hash functions are expected to have a so-called <em>avalanche effect</em> which means
that the smallest change to the key should result in a massive change of hash.
Avalanche effect technically guarantees that even when your data are clustered
together, it should lower the amount of conflicts that can occur.</p>
<divclass="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><divclass="admonitionHeading_Gvgb"><spanclass="admonitionIcon_Rf37"><svgviewBox="0 0 12 16"><pathfill-rule="evenodd"d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Exercise for the reader</div><divclass="admonitionContent_BuS1"><p>Try to give an example of a hash function that is not good at all.</p></div></div>
<h3class="anchor anchorWithStickyNavbar_LWe7"id="implementation-details">Implementation details<ahref="#implementation-details"class="hash-link"aria-label="Direct link to Implementation details"title="Direct link to Implementation details"></a></h3>
<p>There are different variations of the hash tables. You've more than likely seen
an implementation that keeps linked lists for buckets. However there are also
other variations that use probing instead.</p>
<p>With regards to the implementation details, we need to mention the fact that
even with the bounded hash (as we could've seen above), you're not likely to
have all the buckets for different hashes available. Most common approach to
this is having a smaller set of buckets and modifying the hash to fit within.</p>
<p>One of the most common approaches is to keep lengths of the hash tables in the
powers of 2 which allows bit-masking to take place.</p>
hash table. What can we do here?</p><p>Well, we definitely have a bigger hash than spots available, so we need to
“shrink” it somehow. The most common practice is to take the lower bits of the
hash to represent an index in the table:</p><divclass="codeBlockContainer_Ckt0 theme-code-block"style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><divclass="codeBlockContent_biex"><pretabindex="0"class="prism-code language-text codeBlock_bY9V thin-scrollbar"style="color:#393A34;background-color:#f6f8fa"><codeclass="codeBlockLines_e6Vv"><spanclass="token-line"style="color:#393A34"><spanclass="token plain">h & (l - 1)</span><br></span></code></pre><divclass="buttonGroup__atx"><buttontype="button"aria-label="Copy code to clipboard"title="Copy"class="clean-btn"><spanclass="copyButtonIcons_eSgA"aria-hidden="true"><svgviewBox="0 0 24 24"class="copyButtonIcon_y97N"><pathfill="currentColor"d="M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"></path></svg><svgviewBox="0 0 24 24"class="copyButtonSuccessIcon_LjdS"><pathfill="currentColor"d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"></path></svg></span></button></div></div></div><p><em>Why does this work?</em> Firstly we subtract 1 from the length (indices run from
<code>⟨0 ; l - 1⟩</code>, since table is zero-indexed). Therefore if we do <em>binary and</em> on
any number, we always get a valid index within the table. Let's find the index
<sectiondata-footnotes="true"class="footnotes"><h2class="anchor anchorWithStickyNavbar_LWe7 sr-only"id="footnote-label">Footnotes<ahref="#footnote-label"class="hash-link"aria-label="Direct link to Footnotes"title="Direct link to Footnotes"></a></h2>
<ol>
<liid="user-content-fn-1">
<p>not true <ahref="#user-content-fnref-1"data-footnote-backref=""aria-label="Back to reference 1"class="data-footnote-backref">↩</a></p>
</li>
<liid="user-content-fn-2">
<p>also not true <ahref="#user-content-fnref-2"data-footnote-backref=""aria-label="Back to reference 2"class="data-footnote-backref">↩</a></p>
</li>
<liid="user-content-fn-3">
<p>actually the first of its kind (the self-balanced trees) <ahref="#user-content-fnref-3"data-footnote-backref=""aria-label="Back to reference 3"class="data-footnote-backref">↩</a></p>
</li>
<liid="user-content-fn-4">
<p>Rust chose to implement this instead of the common choice of the red-black
or AVL tree; main difference lies in the fact that B-trees are not binary
trees <ahref="#user-content-fnref-4"data-footnote-backref=""aria-label="Back to reference 4"class="data-footnote-backref">↩</a></p>
</li>
<liid="user-content-fn-5">
<p>This, of course, does not hold true for the educational implementations of
the hash tables where conflicts are handled by storing the items in the
linked lists. In practice linked lists are not that commonly used for
addressing this issue as it has even worse impact on the efficiency of the
data structure. <ahref="#user-content-fnref-5"data-footnote-backref=""aria-label="Back to reference 5"class="data-footnote-backref">↩</a></p>
</li>
<liid="user-content-fn-6">
<p>My guess is not very good, or it's really bad… <ahref="#user-content-fnref-6"data-footnote-backref=""aria-label="Back to reference 6"class="data-footnote-backref">↩</a></p>
</li>
<liid="user-content-fn-7">
<p><ahref="https://en.cppreference.com/w/cpp/utility/hash"target="_blank"rel="noopener noreferrer">https://en.cppreference.com/w/cpp/utility/hash</a><ahref="#user-content-fnref-7"data-footnote-backref=""aria-label="Back to reference 7"class="data-footnote-backref">↩</a></p>