This commit is contained in:
krahets
2023-09-21 20:44:52 +08:00
parent 830dc9e326
commit 0ba5acd92b
111 changed files with 13161 additions and 5302 deletions

View File

@ -3444,7 +3444,32 @@
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<!--
Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
-->
<!-- Tags -->
<!-- Actions -->
<a href="https://github.com/krahets/hello-algo/tree/main/docs/chapter_hashing/hash_map.md" title="编辑此页" class="md-content__button md-icon">
@ -3455,6 +3480,13 @@
<!--
Hack: check whether the content contains a h1 headline. If it doesn't, the
page title (or respectively site name) is used as the main headline.
-->
<!-- Page content -->
<h1 id="61">6.1 &nbsp; 哈希表<a class="headerlink" href="#61" title="Permanent link">&para;</a></h1>
<p>「哈希表 hash table」又称「散列表」其通过建立键 <code>key</code> 与值 <code>value</code> 之间的映射,实现高效的元素查询。具体而言,我们向哈希表输入一个键 <code>key</code> ,则可以在 <span class="arithmatex">\(O(1)\)</span> 时间内获取对应的值 <code>value</code></p>
<p>如图 6-1 所示,给定 <span class="arithmatex">\(n\)</span> 个学生,每个学生都有“姓名”和“学号”两项数据。假如我们希望实现“输入一个学号,返回对应的姓名”的查询功能,则可以采用图 6-1 所示的哈希表来实现。</p>
@ -4543,11 +4575,10 @@
<a id="__codelineno-31-77" name="__codelineno-31-77" href="#__codelineno-31-77"></a><span class="w"> </span><span class="nx">print</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-31-78" name="__codelineno-31-78" href="#__codelineno-31-78"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">pairSet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">entries</span><span class="p">();</span>
<a id="__codelineno-31-79" name="__codelineno-31-79" href="#__codelineno-31-79"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">pair</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">pairSet</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-31-80" name="__codelineno-31-80" href="#__codelineno-31-80"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">pair</span><span class="p">)</span><span class="w"> </span><span class="k">continue</span><span class="p">;</span>
<a id="__codelineno-31-81" name="__codelineno-31-81" href="#__codelineno-31-81"></a><span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="sb">`</span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">key</span><span class="si">}</span><span class="sb"> -&gt; </span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">val</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
<a id="__codelineno-31-82" name="__codelineno-31-82" href="#__codelineno-31-82"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-31-83" name="__codelineno-31-83" href="#__codelineno-31-83"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-31-84" name="__codelineno-31-84" href="#__codelineno-31-84"></a><span class="p">}</span>
<a id="__codelineno-31-80" name="__codelineno-31-80" href="#__codelineno-31-80"></a><span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="sb">`</span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">key</span><span class="si">}</span><span class="sb"> -&gt; </span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">val</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
<a id="__codelineno-31-81" name="__codelineno-31-81" href="#__codelineno-31-81"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-31-82" name="__codelineno-31-82" href="#__codelineno-31-82"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-31-83" name="__codelineno-31-83" href="#__codelineno-31-83"></a><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@ -4634,11 +4665,10 @@
<a id="__codelineno-32-81" name="__codelineno-32-81" href="#__codelineno-32-81"></a><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="nx">print</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-32-82" name="__codelineno-32-82" href="#__codelineno-32-82"></a><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nx">pairSet</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">entries</span><span class="p">();</span>
<a id="__codelineno-32-83" name="__codelineno-32-83" href="#__codelineno-32-83"></a><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">pair</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">pairSet</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<a id="__codelineno-32-84" name="__codelineno-32-84" href="#__codelineno-32-84"></a><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">pair</span><span class="p">)</span><span class="w"> </span><span class="k">continue</span><span class="p">;</span>
<a id="__codelineno-32-85" name="__codelineno-32-85" href="#__codelineno-32-85"></a><span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="sb">`</span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">key</span><span class="si">}</span><span class="sb"> -&gt; </span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">val</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
<a id="__codelineno-32-86" name="__codelineno-32-86" href="#__codelineno-32-86"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-32-87" name="__codelineno-32-87" href="#__codelineno-32-87"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-32-88" name="__codelineno-32-88" href="#__codelineno-32-88"></a><span class="p">}</span>
<a id="__codelineno-32-84" name="__codelineno-32-84" href="#__codelineno-32-84"></a><span class="w"> </span><span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="sb">`</span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">key</span><span class="si">}</span><span class="sb"> -&gt; </span><span class="si">${</span><span class="nx">pair</span><span class="p">.</span><span class="nx">val</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
<a id="__codelineno-32-85" name="__codelineno-32-85" href="#__codelineno-32-85"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-32-86" name="__codelineno-32-86" href="#__codelineno-32-86"></a><span class="w"> </span><span class="p">}</span>
<a id="__codelineno-32-87" name="__codelineno-32-87" href="#__codelineno-32-87"></a><span class="p">}</span>
</code></pre></div>
</div>
<div class="tabbed-block">
@ -4937,11 +4967,73 @@
<p>类似于数组扩容,哈希表扩容需将所有键值对从原哈希表迁移至新哈希表,非常耗时。并且由于哈希表容量 <code>capacity</code> 改变,我们需要通过哈希函数来重新计算所有键值对的存储位置,这进一步提高了扩容过程的计算开销。为此,编程语言通常会预留足够大的哈希表容量,防止频繁扩容。</p>
<p>「负载因子 load factor」是哈希表的一个重要概念其定义为哈希表的元素数量除以桶数量用于衡量哈希冲突的严重程度<strong>也常被作为哈希表扩容的触发条件</strong>。例如在 Java 中,当负载因子超过 <span class="arithmatex">\(0.75\)</span> 时,系统会将哈希表容量扩展为原先的 <span class="arithmatex">\(2\)</span> 倍。</p>
<!-- Source file information -->
<!-- Was this page helpful? -->
<h2 id="__comments">评论</h2>
<!-- Previous and next pages link -->
<nav
class="md-footer__inner md-grid"
aria-label="页脚"
>
<!-- Link to previous page -->
<a
href="../"
class="md-footer__link md-footer__link--prev"
aria-label="上一页: 第 6 章 &amp;nbsp; 哈希表"
rel="prev"
>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
上一页
</span>
<div class="md-ellipsis">
第 6 章 &nbsp; 哈希表
</div>
</div>
</a>
<!-- Link to next page -->
<a
href="../hash_collision/"
class="md-footer__link md-footer__link--next"
aria-label="下一页: 6.2 &amp;nbsp; 哈希冲突"
rel="next"
>
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
6.2 &nbsp; 哈希冲突
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg>
</div>
</a>
</nav>
<!-- Comment system -->
<h5 align="center" id="__comments">欢迎你提出疑问或建议</h5>
<!-- Insert generated snippet here -->
<script
src="https://giscus.app/client.js"
@ -5007,48 +5099,31 @@
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../" class="md-footer__link md-footer__link--prev" aria-label="上一页: 第 6 章 &amp;nbsp; 哈希表" rel="prev">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
上一页
</span>
<div class="md-ellipsis">
第 6 章 &nbsp; 哈希表
</div>
</div>
</a>
<a href="../hash_collision/" class="md-footer__link md-footer__link--next" aria-label="下一页: 6.2 &amp;nbsp; 哈希冲突" rel="next">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
6.2 &nbsp; 哈希冲突
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg>
</div>
</a>
</nav>
<!--
Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
-->
<!-- Footer -->
<footer class="md-footer">
<!-- Further information -->
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
@ -5059,6 +5134,8 @@
</div>
<!-- Social links -->
<div class="md-social">