{"id":5041,"date":"2016-11-24T06:32:50","date_gmt":"2016-11-24T06:32:50","guid":{"rendered":"https:\/\/www.modernescpp.com\/index.php\/hash-tables\/"},"modified":"2023-06-26T12:35:24","modified_gmt":"2023-06-26T12:35:24","slug":"hash-tables","status":"publish","type":"post","link":"https:\/\/www.modernescpp.com\/index.php\/hash-tables\/","title":{"rendered":"Hash Tables"},"content":{"rendered":"<p>We missed the hash table in C++ for a long time. They promise to have constant access time. C++11 has hash tables in four variations. The official name is unordered associative containers. Unofficially, they are called dictionaries or just simple associative arrays.&nbsp;<\/p>\n<p><!--more--><\/p>\n<p>Classical C++ has four different associative containers. With C++11, we get four additional ones. First, we need a systematic.<\/p>\n<h2>Associative container<\/h2>\n<p>All associative containers have in common that they associated a key with a value. Therefore, you can get the value by using the key. The classical associative containers are called ordered associative containers; the new ones are unordered associative containers.<\/p>\n<h3>Ordered associative containers<\/h3>\n<p>The small difference is that the keys of the classical associative containers are ordered. By default, the smaller relation (<strong>&lt;<\/strong>) is used. Therefore, the containers are sorted in increasing order.<\/p>\n<p>This ordering has exciting consequences for the ordered associative containers.<\/p>\n<ul>\n<li>The key has to support an ordering relation.<\/li>\n<li>Associative containers are typically implemented in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Self-balancing_binary_search_tree\">balanced binary search trees<\/a>.<\/li>\n<li>The access time to the key and, therefore, to the value is logarithmic.<\/li>\n<\/ul>\n<p>The most often used ordered associative container is <span style=\"font-family: courier new,courier;\">std::map:<\/span><\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0; line-height: 125%;\">map&lt;<span style=\"color: #2b91af;\">int<\/span>, string&gt; int2String{ {3,<span style=\"color: #a31515;\">\"three\"<\/span>},{2,<span style=\"color: #a31515;\">\"two\"<\/span>},{1,<span style=\"color: #a31515;\">\"one\"<\/span>},{5,<span style=\"color: #a31515;\">\"five\"<\/span>},{6,<span style=\"color: #a31515;\">\"six\"<\/span>},{4,<span style=\"color: #a31515;\">\"four\"<\/span>},{7,<span style=\"color: #a31515;\">\"seven\"<\/span>} };\r\n<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<p>The balanced binary search tree may have the following structure.<\/p>\n<p>&nbsp;<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5037\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/geordneteAssoziativeArrays.png\" alt=\"geordneteAssoziativeArrays\" width=\"475\" height=\"265\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/geordneteAssoziativeArrays.png 475w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/geordneteAssoziativeArrays-300x167.png 300w\" sizes=\"auto, (max-width: 475px) 100vw, 475px\" \/><\/p>\n<\/p>\n<h2>Unordered associative containers<\/h2>\n<p>The key idea of the unordered associative containers is that the key is mapped with the help of the hash function onto the bucket. You can find the key\/value pair in the bucket.<\/p>\n<p>I have to introduce a few terms before I describe the characteristics of unordered associative containers.<\/p>\n<ul>\n<li><strong>Hash value<\/strong>: The value you will get if you apply the hash function to the key.<\/li>\n<li><strong>Collision<\/strong>: We will collide if different keys are mapped to the same hash value. The unordered associative containers have to deal with this situation.<\/li>\n<\/ul>\n<p>The usage of the hash function has very important consequences for the unordered associative container.<\/p>\n<ul>\n<li>The keys have to support equal comparison to deal with collisions.<\/li>\n<li>The hash value of a key has to be available.<\/li>\n<li>The execution of a hash function is a constant. Therefore, the access time to the keys of an unordered associative container is constant. For simplicity reasons I ignored collisions.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>According to <span style=\"font-family: courier new,courier;\">std::map<\/span> is the most often used ordered associative container <span style=\"font-family: courier new,courier;\">std::unordered_map<\/span> will become the most often used unordered associative container.<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<pre style=\"margin: 0px; line-height: 125%;\">unordered_map&lt;string,<span style=\"color: #2b91af;\">int<\/span>&gt; str2Int{ {<span style=\"color: #a31515;\">\"<span style=\"color: #ff0000;\">Grimm<\/span>\"<\/span>,491634333356},{<span style=\"color: #a31515;\">\"<span style=\"color: #ff0000;\">Grimm-Jaud<\/span><\/span><span style=\"color: #a31515;\">\",<span style=\"color: #000000;\">49160123335<\/span>}, {\"<\/span><span style=\"color: #ff0000;\">Schmid<\/span>t<span style=\"color: #a31515;\">\",<span style=\"color: #000000;\">4913333318<\/span>},{\"<\/span><span style=\"color: #ff0000;\">Huber<\/span><span style=\"color: #a31515;\">\",<span style=\"color: #000000;\">490001326<\/span>} };<\/span>\r\n&nbsp;<\/pre>\n<\/div>\n<p>The graphic shows the mapping of the keys to their bucket by using the hash function.<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5038\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/UngeordnetesAssoziativesArrayEng.png\" alt=\"UngeordnetesAssoziativesArrayEng\" width=\"387\" height=\"342\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/UngeordnetesAssoziativesArrayEng.png 387w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/UngeordnetesAssoziativesArrayEng-300x265.png 300w\" sizes=\"auto, (max-width: 387px) 100vw, 387px\" \/><\/h2>\n<h2>The similarities<\/h2>\n<p>The similar names of <span style=\"font-family: courier new,courier;\">std::map<\/span> and <span style=\"font-family: courier new,courier;\">std::unordered_map<\/span> are not by accident. Both have a similar interface. To be more precise. The interface of <span style=\"font-family: courier new,courier;\">std::map<\/span> is a subset of the interface of <span style=\"font-family: courier new,courier;\">std::unorederd_map.<\/span> Have a look:<\/p>\n<p>&nbsp;<\/p>\n<p><!-- HTML generated using hilite.me --><\/p>\n<div style=\"background: #ffffff; overflow: auto; width: auto; gray;border-width: .1em .1em .1em .8em;\">\n<table>\n<tbody>\n<tr>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"> 1\r\n 2\r\n 3\r\n 4\r\n 5\r\n 6\r\n 7\r\n 8\r\n 9\r\n10\r\n11\r\n12\r\n13\r\n14\r\n15\r\n16\r\n17\r\n18\r\n19\r\n20\r\n21\r\n22\r\n23\r\n24\r\n25\r\n26\r\n27\r\n28\r\n29\r\n30\r\n31\r\n32\r\n33\r\n34\r\n35\r\n36\r\n37\r\n38\r\n39\r\n40<\/pre>\n<\/td>\n<td>\n<pre style=\"margin: 0; line-height: 125%;\"><span style=\"color: #008000;\">\/\/ mapHashCompare.cpp<\/span>\r\n\r\n<span style=\"color: #0000ff;\">#include &lt;iostream&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;map&gt;<\/span>\r\n<span style=\"color: #0000ff;\">#include &lt;unordered_map&gt;<\/span>\r\n\r\n<span style=\"color: #2b91af;\">int<\/span> main(){\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"C++ map: \"<\/span> &lt;&lt; std::endl;\r\n  std::map&lt;std::string,<span style=\"color: #2b91af;\">int<\/span>&gt; m { {<span style=\"color: #a31515;\">\"Dijkstra\"<\/span>,1972},{<span style=\"color: #a31515;\">\"Scott\"<\/span>,1976} };\r\n  m[<span style=\"color: #a31515;\">\"Ritchie\"<\/span>] = 1983;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"    m[Ritchie]: \"<\/span> &lt;&lt;  m[<span style=\"color: #a31515;\">\"Ritchie\"<\/span>] &lt;&lt; <span style=\"color: #a31515;\">\"\\n    \"<\/span>;\r\n  <span style=\"color: #0000ff;\">for<\/span>(<span style=\"color: #0000ff;\">auto<\/span> p : m) std::cout &lt;&lt; <span style=\"color: #a31515;\">'{'<\/span> &lt;&lt; p.first &lt;&lt; <span style=\"color: #a31515;\">','<\/span> &lt;&lt; p.second &lt;&lt; <span style=\"color: #a31515;\">'}'<\/span>;\r\n  m.erase(<span style=\"color: #a31515;\">\"Scott\"<\/span>);\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"\\n    \"<\/span>;\r\n  <span style=\"color: #0000ff;\">for<\/span>(<span style=\"color: #0000ff;\">auto<\/span> p : m) std::cout &lt;&lt; <span style=\"color: #a31515;\">'{'<\/span> &lt;&lt; p.first &lt;&lt; <span style=\"color: #a31515;\">','<\/span> &lt;&lt; p.second &lt;&lt; <span style=\"color: #a31515;\">'}'<\/span>;\r\n  m.clear();\r\n  std::cout &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"    m.size(): \"<\/span> &lt;&lt; m.size() &lt;&lt; std::endl;\r\n\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"C++11 unordered_map: \"<\/span> &lt;&lt; std::endl;\r\n  std::unordered_map&lt;std::string,<span style=\"color: #2b91af;\">int<\/span>&gt; um { {<span style=\"color: #a31515;\">\"Dijkstra\"<\/span>,1972},{<span style=\"color: #a31515;\">\"Scott\"<\/span>,1976} };\r\n  um[<span style=\"color: #a31515;\">\"Ritchie\"<\/span>] = 1983;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"    um[Ritchie]: \"<\/span> &lt;&lt;  um[<span style=\"color: #a31515;\">\"Ritchie\"<\/span>] &lt;&lt; <span style=\"color: #a31515;\">\"\\n    \"<\/span>;\r\n  <span style=\"color: #0000ff;\">for<\/span>(<span style=\"color: #0000ff;\">auto<\/span> p : um) std::cout &lt;&lt; <span style=\"color: #a31515;\">'{'<\/span> &lt;&lt; p.first &lt;&lt; <span style=\"color: #a31515;\">','<\/span> &lt;&lt; p.second &lt;&lt; <span style=\"color: #a31515;\">'}'<\/span>;\r\n  um.erase(<span style=\"color: #a31515;\">\"Scott\"<\/span>);\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"\\n    \"<\/span>;\r\n  <span style=\"color: #0000ff;\">for<\/span>(<span style=\"color: #0000ff;\">auto<\/span> p : um) std::cout &lt;&lt; <span style=\"color: #a31515;\">'{'<\/span> &lt;&lt; p.first &lt;&lt; <span style=\"color: #a31515;\">','<\/span> &lt;&lt; p.second &lt;&lt; <span style=\"color: #a31515;\">'}'<\/span>;\r\n  um.clear();\r\n  std::cout &lt;&lt; std::endl;\r\n  std::cout &lt;&lt; <span style=\"color: #a31515;\">\"    um.size(): \"<\/span> &lt;&lt; um.size() &lt;&lt; std::endl;\r\n\r\n  std::cout &lt;&lt; std::endl;\r\n\r\n}\r\n<\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<div>&nbsp;<\/div>\n<div>A typical case of <em>copy and paste<\/em>. The difference between lines 11 &#8211; 21 and 26 &#8211; 36 is only that I used in the first case <span style=\"font-family: courier new,courier;\">std::map<\/span>; that I used in the second case <span style=\"font-family: courier new,courier;\">std::unordered_map. <\/span>Therefore, I will only explain the second case. I initialized in line 27 the <span style=\"font-family: courier new,courier;\">std::unordered_map<\/span> with the help of an initializer list. Then I update the value of the key <span style=\"font-family: courier new,courier;\">&#8220;Richie&#8221;<\/span>&nbsp; <span style=\"font-family: courier new,courier;\"><\/span>and return the associated value. In lines 30 and 33, I display the key\/values pairs by using a range-based for-loop. <span style=\"font-family: courier new,courier;\">p.first<\/span> is the first, <span style=\"font-family: courier new,courier;\">p.second<\/span> is the second element of the pair. By using <span style=\"font-family: courier new,courier;\">um.clear() <\/span>I can clear the unordered associative container by using <span style=\"font-family: courier new,courier;\">um.size()<\/span> I can determine its size.<\/div>\n<div>&nbsp;<\/div>\n<div>A second glance reveals a small difference.<\/div>\n<div>&nbsp;.<\/div>\n<div><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5039\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/mapHashCompare.png\" alt=\"mapHashCompare\" width=\"599\" height=\"327\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/mapHashCompare.png 599w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/mapHashCompare-300x164.png 300w\" sizes=\"auto, (max-width: 599px) 100vw, 599px\" \/><\/div>\n<p>&nbsp;<\/p>\n<p>The keys of the std::maps are ordered and, therefore, the pairs. Surprised? Of course not! That is the visible difference between the ordered and unordered associative containers.<\/p>\n<h2>The eight variations<\/h2>\n<p>I start with the classically ordered associative containers to get an ordering into the eight variations. You can easily apply the ordering to the unordered associative containers.<\/p>\n<p>The answers to two questions are the key to getting systematic into ordered associative containers:<\/p>\n<ul>\n<li>Does the key have an associated value?<\/li>\n<li>Are several identical keys possible?<\/li>\n<\/ul>\n<p>You get the four ordered associative containers std::set, std::multiset, std::map, and std::multimap by answering the two questions<span style=\"font-family: courier new,courier;\">.<\/span><\/p>\n<p>Of course, you can apply the two questions to the unordered associative containers. Now you get the containers <span style=\"font-family: courier new,courier;\">std::unordered_set, std::unordered_multiset, std::unordered_map<\/span>, and<span style=\"font-family: courier new,courier;\"> std::unordered_multimap.<\/span><\/p>\n<p>&nbsp;All that is left is to write down the systematic. If the container&#8217;s name has the component<\/p>\n<ul>\n<li><strong>map, <\/strong>it has an associated value.<\/li>\n<li><strong>multi<\/strong>, it can have more than one identical key.&nbsp;<\/li>\n<li><strong>unordered<\/strong>, its keys are non-sorted.<\/li>\n<\/ul>\n<p>But the analogy goes on. If two container names only differ in the name component <strong>unordered,<\/strong> they will have a similar interface. The container without the name component unordered supports an interface that is a subset of the unordered container. You saw it already in the listing <span style=\"font-family: courier new,courier;\">mapHashCompare.cpp.<\/span><\/p>\n<p>The table shows once more the entire system. The systematic includes the access time for the ordered containers (logarithmic) and the unordered container (constant).<\/p>\n<h2><img loading=\"lazy\" decoding=\"async\" class=\" size-full wp-image-5040\" src=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/OrderedVersusUnorderedContainers.png\" alt=\"OrderedVersusUnorderedContainers\" width=\"700\" height=\"298\" style=\"margin: 15px;\" srcset=\"https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/OrderedVersusUnorderedContainers.png 955w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/OrderedVersusUnorderedContainers-300x128.png 300w, https:\/\/www.modernescpp.com\/wp-content\/uploads\/2016\/11\/OrderedVersusUnorderedContainers-768x327.png 768w\" sizes=\"auto, (max-width: 700px) 100vw, 700px\" \/><\/h2>\n<h2>What&#8217;s next?<\/h2>\n<p>My first plan was to show you the performance difference between ordered and unordered containers. So, I will do it in the <a href=\"https:\/\/www.modernescpp.com\/index.php\/associative-containers-a-simple-performance-comparison\">next post.<\/a><span id=\"transmark\"><\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: courier new,courier;\"><a href=\"https:\/\/www.modernescpp.com\/index.php\/source-code-repository\"><\/a><br \/><\/span><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We missed the hash table in C++ for a long time. They promise to have constant access time. C++11 has hash tables in four variations. The official name is unordered associative containers. Unofficially, they are called dictionaries or just simple associative arrays.&nbsp;<\/p>\n","protected":false},"author":21,"featured_media":5037,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[364],"tags":[472],"class_list":["post-5041","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-embedded","tag-associative-containers"],"_links":{"self":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5041","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/users\/21"}],"replies":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/comments?post=5041"}],"version-history":[{"count":1,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5041\/revisions"}],"predecessor-version":[{"id":6923,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/posts\/5041\/revisions\/6923"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media\/5037"}],"wp:attachment":[{"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/media?parent=5041"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/categories?post=5041"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.modernescpp.com\/index.php\/wp-json\/wp\/v2\/tags?post=5041"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}